... | ... |
@@ -192,7 +192,7 @@ int main(int argc, char *argv[]) |
192 | 192 |
bcs.all_bcs = bc; |
193 | 193 |
bcs.count = 1; |
194 | 194 |
|
195 |
- rc = cli_bytecode_load(bc, f, NULL); |
|
195 |
+ rc = cli_bytecode_load(bc, f, NULL, 0); |
|
196 | 196 |
if (rc != CL_SUCCESS) { |
197 | 197 |
fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc)); |
198 | 198 |
optfree(opts); |
... | ... |
@@ -410,6 +410,23 @@ int main(int argc, char **argv) |
410 | 410 |
if(optget(opts,"Bytecode")->enabled) |
411 | 411 |
dboptions |= CL_DB_BYTECODE; |
412 | 412 |
|
413 |
+ if((opt = optget(opts,"BytecodeSecurity"))->enabled) { |
|
414 |
+ enum bytecode_security s; |
|
415 |
+ if (!strcmp(opt->strarg, "TrustSigned")) |
|
416 |
+ s = CL_BYTECODE_TRUST_SIGNED; |
|
417 |
+ else if (!strcmp(opt->strarg, "None")) |
|
418 |
+ s = CL_BYTECODE_TRUST_ALL; |
|
419 |
+ else if (!strcmp(opt->strarg, "Paranoid")) |
|
420 |
+ s = CL_BYTECODE_TRUST_NOTHING; |
|
421 |
+ else { |
|
422 |
+ logg("!Unable to parse bytecode security setting:%s\n", |
|
423 |
+ opt->strarg); |
|
424 |
+ ret = 1; |
|
425 |
+ break; |
|
426 |
+ } |
|
427 |
+ cl_engine_set_num(engine, CL_ENGINE_BYTECODE_SECURITY, s); |
|
428 |
+ } |
|
429 |
+ |
|
413 | 430 |
if(optget(opts,"PhishingScanURLs")->enabled) |
414 | 431 |
dboptions |= CL_DB_PHISHING_URLS; |
415 | 432 |
else |
... | ... |
@@ -442,3 +442,14 @@ LocalSocket /tmp/clamd.socket |
442 | 442 |
# Set the exclude paths. All subdirectories are also excluded. (Dazuko only) |
443 | 443 |
# Default: disabled |
444 | 444 |
#ClamukoExcludePath /home/bofh |
445 |
+ |
|
446 |
+# Set bytecode security level. |
|
447 |
+# Possible values: |
|
448 |
+# None - no security at all, meant for debugging. DO NOT USE THIS ON PRODUCTION SYSTEMS |
|
449 |
+# TrustSigned - trust bytecode loaded from signed .c[lv]d files, |
|
450 |
+# insert runtime safety checks for bytecode loaded from other sources |
|
451 |
+# Paranoid - don't trust any bytecode, insert runtime checks for all |
|
452 |
+# Recommended: TrustSigned, because bytecode in .cvd files already has these checks |
|
453 |
+# |
|
454 |
+# Default: TrustSigned |
|
455 |
+#BytecodeSecurity TrustSigned |
... | ... |
@@ -1222,7 +1222,7 @@ enum parse_state { |
1222 | 1222 |
PARSE_BB |
1223 | 1223 |
}; |
1224 | 1224 |
|
1225 |
-int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) |
|
1225 |
+int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int trust) |
|
1226 | 1226 |
{ |
1227 | 1227 |
unsigned row = 0, current_func = 0, bb=0; |
1228 | 1228 |
char *buffer; |
... | ... |
@@ -1232,6 +1232,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) |
1232 | 1232 |
int rc; |
1233 | 1233 |
|
1234 | 1234 |
memset(bc, 0, sizeof(*bc)); |
1235 |
+ bc->trusted = trust; |
|
1235 | 1236 |
if (!f && !dbio) { |
1236 | 1237 |
cli_errmsg("Unable to load bytecode (null file)\n"); |
1237 | 1238 |
return CL_ENULLARG; |
... | ... |
@@ -67,6 +67,7 @@ struct cli_bc { |
67 | 67 |
struct cli_bc_dbgnode *dbgnodes; |
68 | 68 |
unsigned dbgnode_cnt; |
69 | 69 |
unsigned hook_lsig_id; |
70 |
+ unsigned trusted; |
|
70 | 71 |
}; |
71 | 72 |
|
72 | 73 |
struct cli_all_bc { |
... | ... |
@@ -99,7 +100,7 @@ extern int have_clamjit; |
99 | 99 |
} |
100 | 100 |
#endif |
101 | 101 |
int cli_bytecode_init(struct cli_all_bc *allbc); |
102 |
-int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio); |
|
102 |
+int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int security); |
|
103 | 103 |
int cli_bytecode_prepare(struct cli_all_bc *allbc); |
104 | 104 |
int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx); |
105 | 105 |
void cli_bytecode_destroy(struct cli_bc *bc); |
... | ... |
@@ -134,7 +134,14 @@ enum cl_engine_field { |
134 | 134 |
CL_ENGINE_AC_MINDEPTH, /* uint32_t */ |
135 | 135 |
CL_ENGINE_AC_MAXDEPTH, /* uint32_t */ |
136 | 136 |
CL_ENGINE_TMPDIR, /* (char *) */ |
137 |
- CL_ENGINE_KEEPTMP /* uint32_t */ |
|
137 |
+ CL_ENGINE_KEEPTMP, /* uint32_t */ |
|
138 |
+ CL_ENGINE_BYTECODE_SECURITY /* uint32_t */ |
|
139 |
+}; |
|
140 |
+ |
|
141 |
+enum bytecode_security { |
|
142 |
+ CL_BYTECODE_TRUST_ALL=0, /* insecure, debug setting */ |
|
143 |
+ CL_BYTECODE_TRUST_SIGNED, /* default */ |
|
144 |
+ CL_BYTECODE_TRUST_NOTHING /* paranoid setting */ |
|
138 | 145 |
}; |
139 | 146 |
|
140 | 147 |
extern int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long long num); |
... | ... |
@@ -300,6 +300,7 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un |
300 | 300 |
dbio->readpt = dbio->buf; |
301 | 301 |
cli_md5_init(&dbio->md5ctx); |
302 | 302 |
dbio->bread = 0; |
303 |
+ dbio->secure = 0; |
|
303 | 304 |
|
304 | 305 |
/* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */ |
305 | 306 |
if(compr) |
... | ... |
@@ -291,6 +291,7 @@ struct cl_engine *cl_engine_new(void) |
291 | 291 |
new->min_cc_count = CLI_DEFAULT_MIN_CC_COUNT; |
292 | 292 |
new->min_ssn_count = CLI_DEFAULT_MIN_SSN_COUNT; |
293 | 293 |
|
294 |
+ new->bytecode_security = CL_BYTECODE_TRUST_SIGNED; |
|
294 | 295 |
new->refcount = 1; |
295 | 296 |
new->ac_only = 0; |
296 | 297 |
new->ac_mindepth = CLI_DEFAULT_AC_MINDEPTH; |
... | ... |
@@ -373,6 +374,9 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long |
373 | 373 |
case CL_ENGINE_KEEPTMP: |
374 | 374 |
engine->keeptmp = num; |
375 | 375 |
break; |
376 |
+ case CL_ENGINE_BYTECODE_SECURITY: |
|
377 |
+ engine->bytecode_security = num; |
|
378 |
+ break; |
|
376 | 379 |
default: |
377 | 380 |
cli_errmsg("cl_engine_set_num: Incorrect field number\n"); |
378 | 381 |
return CL_EARG; |
... | ... |
@@ -1316,6 +1316,8 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
1316 | 1316 |
struct cli_all_bc *bcs = &engine->bcs; |
1317 | 1317 |
struct cli_bc *bc; |
1318 | 1318 |
unsigned sigs = 0; |
1319 |
+ unsigned security_trust = 0; |
|
1320 |
+ |
|
1319 | 1321 |
|
1320 | 1322 |
/* TODO: virusname have a common prefix, and whitelist by that */ |
1321 | 1323 |
if((rc = cli_initroots(engine, options))) |
... | ... |
@@ -1331,7 +1333,25 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
1331 | 1331 |
} |
1332 | 1332 |
bcs->count++; |
1333 | 1333 |
bc = &bcs->all_bcs[bcs->count-1]; |
1334 |
- rc = cli_bytecode_load(bc, fs, dbio); |
|
1334 |
+ |
|
1335 |
+ switch (engine->bytecode_security) { |
|
1336 |
+ case CL_BYTECODE_TRUST_ALL: |
|
1337 |
+ security_trust = 1; |
|
1338 |
+ cli_dbgmsg("bytecode: trusting all bytecode!\n"); |
|
1339 |
+ break; |
|
1340 |
+ case CL_BYTECODE_TRUST_SIGNED: |
|
1341 |
+ if (dbio && (!engine->dbinfo || !engine->dbinfo->cvd |
|
1342 |
+ || !engine->dbinfo->cvd->dsig)) { |
|
1343 |
+ cli_errmsg("CVD without signed .info?\n"); |
|
1344 |
+ return CL_EMALFDB; |
|
1345 |
+ } |
|
1346 |
+ security_trust = dbio ? 1 : 0; |
|
1347 |
+ break; |
|
1348 |
+ default: |
|
1349 |
+ security_trust = 0; |
|
1350 |
+ } |
|
1351 |
+ |
|
1352 |
+ rc = cli_bytecode_load(bc, fs, dbio, security_trust); |
|
1335 | 1353 |
if (rc != CL_SUCCESS) { |
1336 | 1354 |
cli_errmsg("Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc)); |
1337 | 1355 |
return rc; |
... | ... |
@@ -240,6 +240,8 @@ const struct clam_option __clam_options[] = { |
240 | 240 |
|
241 | 241 |
/* Scan options */ |
242 | 242 |
{ "Bytecode", "bytecode", 0, TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled ClamAV will load bytecode from the database. It is highly recommended you keep this option on, otherwise you'll miss detections for many new viruses.", "yes" }, |
243 |
+ { "BytecodeSecurity", NULL, 0, TYPE_STRING, "^(None|TrustSigned|Paranoid)$", -1, "TrustSigned", 0, OPT_CLAMD, |
|
244 |
+ "Set bytecode security level.\nPossible values:\n\tNone - no security at all, meant for debugging. DO NOT USE THIS ON PRODUCTION SYSTEMS\n\tTrustSigned - trust bytecode loaded from signed .c[lv]d files,\n\t\t insert runtime safety checks for bytecode loaded from other sources\n\tParanoid - don't trust any bytecode, insert runtime checks for all\nRecommended: TrustSigned, because bytecode in .cvd files already has these checks\n","TrustSigned"}, |
|
243 | 245 |
{ "DetectPUA", "detect-pua", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" }, |
244 | 246 |
|
245 | 247 |
{ "ExcludePUA", "exclude-pua", 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_CLAMSCAN, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/support/pua for the complete list of PUA\ncategories.", "NetTool\nPWTool" }, |