New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix TOCTOU / CAP_DAC_READ_SEARCH issue w/ call to access() #135
Conversation
|
Per our discussing in IRC, some missing context:
Ideally Running as If a process has That said, there's two ways to bless a process, the good way and the bad way.
|
|
Pending some testing after 0.103 is released, it looks good to me! |
|
@duckfez I was reviewing your PR and would suggest one change. It's not a part of the diff --git a/clamd/scanner.c b/clamd/scanner.c
index 473398696..7968b2501 100644
--- a/clamd/scanner.c
+++ b/clamd/scanner.c
@@ -144,7 +144,6 @@ cl_error_t scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_
int type = scandata->type;
struct cb_context context;
char *real_filename = NULL;
- int save_errno;
if (NULL != filename) {
if (CL_SUCCESS != cli_realpath((const char *)filename, &real_filename)) {
@@ -264,7 +263,6 @@ cl_error_t scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_
context.virsize = 0;
context.scandata = scandata;
ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context);
- save_errno = errno;
thrmgr_setactivetask(NULL, NULL);
if (thrmgr_group_need_terminate(scandata->conn->group)) {
@@ -278,7 +276,7 @@ cl_error_t scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_
ret = CL_EMEM;
}
- if ((ret == CL_EOPEN) && (save_errno == EACCES)) {
+ if (ret == CL_EACCES) {
if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) {
free(filename);
return CL_ETIMEOUT;
diff --git a/libclamav/scanners.c b/libclamav/scanners.c
index 2f46c348d..ec4c502e1 100644
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@ -5094,8 +5094,13 @@ cl_error_t cl_scanfile_callback(const char *filename, const char **virname, unsi
if (!fname)
return CL_EARG;
- if ((fd = safe_open(fname, O_RDONLY | O_BINARY)) == -1)
- return CL_EOPEN;
+ if ((fd = safe_open(fname, O_RDONLY | O_BINARY)) == -1) {
+ if (errno == EACCES) {
+ return CL_EACCES;
+ } else {
+ return CL_EOPEN;
+ }
+ }
if (fname != filename)
free((char *)fname);Otherwise I think the change makes sense. Will send it through testing with my recommendation appended to double-check before any merge. |
|
Oh, regarding Off the top of my head:
Some good news relating to fd-passing though, I found that we can look up filenames by file descriptors for --fdpass scans. I have this working on Linux and Mac, at least. It seems to work well. I'm hoping to include this with other clamonacc bugfixes in the 0.103.1 patch release, soon. |
|
@micahsnyder I think I can live with those changes. You certainly understand the API better than I do. Do you want me to make them? |
|
@duckfez No worries I'll take care of it. Just wanted to run it by you before I did it. |
|
Merged here: 0bc6135...625e506 Thanks again @duckfez |
Call to
access()before attempting to actually open the file in question is a TOCTOU type bug, as the permissions on the file could change between the two operations.Also, this makes using clamd with POSIX capabilities - CAP_DAC_READ_SEARCH specifically - not work because
access()doesn't ask/answer the proper question. See https://access.redhat.com/solutions/1296703.I added
save_errnobecause I didn't know ifthrmgr_setactivetaskorthrmgr_group_need_terminatedid things that would change the value oferrnobefore I got a chance to check it.