diff options
author | Jeff Layton <jlayton@samba.org> | 2010-04-03 06:49:43 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@samba.org> | 2010-04-03 06:49:43 -0400 |
commit | 55c00c67ced28102209e640fd50bcab9d0332a7f (patch) | |
tree | 32a54b390114d8f617e65e761c6d556adc96238d | |
parent | d652b86adc7e9c62ba71b315e91fdd24af0063d8 (diff) | |
download | cifs-utils-55c00c67ced28102209e640fd50bcab9d0332a7f.tar.gz cifs-utils-55c00c67ced28102209e640fd50bcab9d0332a7f.tar.bz2 cifs-utils-55c00c67ced28102209e640fd50bcab9d0332a7f.zip |
mount.cifs: only enable CAP_DAC_OVERRIDE when needed
When dropping capabilities, drop CAP_DAC_OVERRIDE from the effective set
but not the permitted. When we need to open credential or password
files, make it effective again and drop it after the open completes.
This reduces CAP_DAC_OVERRIDE exposure.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
-rw-r--r-- | mount.cifs.c | 210 |
1 files changed, 144 insertions, 66 deletions
diff --git a/mount.cifs.c b/mount.cifs.c index 7d1fa83..1f08230 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -322,21 +322,142 @@ static int parse_username(char *rawuser, struct parsed_mount_info *parsed_info) return 0; } +#ifdef HAVE_LIBCAP +static int +drop_capabilities(int parent) +{ + int rc = 0, ncaps; + cap_t caps; + cap_value_t cap_list[2]; + + caps = cap_get_proc(); + if (caps == NULL) { + fprintf(stderr, "Unable to get current capability set: %s\n", + strerror(errno)); + return EX_SYSERR; + } + + if (cap_clear(caps) == -1) { + fprintf(stderr, "Unable to clear capability set: %s\n", + strerror(errno)); + rc = EX_SYSERR; + goto free_caps; + } + + if (parent || getuid() == 0) { + ncaps = 1; + cap_list[0] = CAP_DAC_OVERRIDE; + if (parent) { + cap_list[1] = CAP_SYS_ADMIN; + ++ncaps; + } + if (cap_set_flag(caps, CAP_PERMITTED, ncaps, cap_list, CAP_SET) == -1) { + fprintf(stderr, "Unable to set permitted capabilities: %s\n", + strerror(errno)); + rc = EX_SYSERR; + goto free_caps; + } + if (parent) { + cap_list[0] = CAP_SYS_ADMIN; + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1) { + fprintf(stderr, "Unable to set effective capabilities: %s\n", + strerror(errno)); + rc = EX_SYSERR; + goto free_caps; + } + } + } + + if (cap_set_proc(caps) != 0) { + fprintf(stderr, "Unable to set current process capabilities: %s\n", + strerror(errno)); + rc = EX_SYSERR; + } +free_caps: + cap_free(caps); + return rc; +} + +static int +toggle_cap_dac_override(int enable) +{ + int rc; + cap_t caps; + cap_value_t cap_list; + + if (getuid() != 0) + return 0; + + caps = cap_get_proc(); + if (caps == NULL) { + fprintf(stderr, "Unable to get current capability set: %s\n", + strerror(errno)); + return EX_SYSERR; + } + + if (cap_clear(caps) == -1) { + fprintf(stderr, "Unable to clear capability set: %s\n", + strerror(errno)); + rc = EX_SYSERR; + goto free_caps; + } + + cap_list = CAP_DAC_OVERRIDE; + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_list, + enable ? CAP_SET : CAP_CLEAR) == -1) { + fprintf(stderr, "Unable to %s effective capabilities: %s\n", + enable ? "set" : "clear", strerror(errno)); + rc = EX_SYSERR; + goto free_caps; + } +free_caps: + cap_free(caps); + return 0; +} +#else /* HAVE_LIBCAP */ +static int +drop_capabilities(int parent) +{ + return 0; +} + +static int +toggle_cap_dac_override(int enable) +{ + return 0; +} +#endif /* HAVE_LIBCAP */ + static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info) { char *line_buf; char *temp_val, *newline; - FILE *fs; + FILE *fs = NULL; int i, length; - i = access(file_name, R_OK); + i = toggle_cap_dac_override(1); if (i) return i; + i = access(file_name, R_OK); + if (i) { + toggle_cap_dac_override(0); + return i; + } + fs = fopen(file_name, "r"); - if (fs == NULL) + if (fs == NULL) { + toggle_cap_dac_override(0); return errno; + } + + i = toggle_cap_dac_override(0); + if (i) { + fclose(fs); + return i; + } + line_buf = (char *)malloc(4096); if (line_buf == NULL) { fclose(fs); @@ -431,20 +552,33 @@ get_password_from_file(int file_descript, char *filename, char buf[sizeof(parsed_info->password) + 1]; if (filename != NULL) { + rc = toggle_cap_dac_override(1); + if (rc) + return rc; + rc = access(filename, R_OK); if (rc) { fprintf(stderr, "mount.cifs failed: access check of %s failed: %s\n", filename, strerror(errno)); + toggle_cap_dac_override(0); return EX_SYSERR; } + file_descript = open(filename, O_RDONLY); if (file_descript < 0) { fprintf(stderr, "mount.cifs failed. %s attempting to open password file %s\n", strerror(errno), filename); + toggle_cap_dac_override(0); return EX_SYSERR; } + + rc = toggle_cap_dac_override(0); + if (rc) { + rc = EX_SYSERR; + goto get_pw_exit; + } } memset(buf, 0, sizeof(buf)); @@ -460,9 +594,8 @@ get_password_from_file(int file_descript, char *filename, rc = set_password(parsed_info, buf); get_pw_exit: - if (filename != NULL) { + if (filename != NULL) close(file_descript); - } return rc; } @@ -1073,7 +1206,7 @@ add_mtab(char *devname, char *mountpoint, unsigned long flags) if (rc != 0) { fprintf(stderr, "Unable to set real uid to effective uid: %s\n", strerror(errno)); - rc = EX_FILEIO; + return EX_FILEIO; } rc = sigfillset(&mask); @@ -1088,6 +1221,10 @@ add_mtab(char *devname, char *mountpoint, unsigned long flags) return EX_FILEIO; } + rc = toggle_cap_dac_override(1); + if (rc) + return EX_FILEIO; + atexit(unlock_mtab); rc = lock_mtab(); if (rc) { @@ -1137,6 +1274,7 @@ add_mtab(char *devname, char *mountpoint, unsigned long flags) unlock_mtab(); SAFE_FREE(mountent.mnt_opts); add_mtab_exit: + toggle_cap_dac_override(0); sigprocmask(SIG_SETMASK, &oldmask, NULL); if (rc) { fprintf(stderr, "unable to add mount entry to mtab\n"); @@ -1146,66 +1284,6 @@ add_mtab_exit: return rc; } -#ifdef HAVE_LIBCAP -static int -drop_capabilities(int parent) -{ - int rc = 0, ncap; - cap_t caps; - cap_value_t cap_list[2]; - - caps = cap_get_proc(); - if (caps == NULL) { - fprintf(stderr, "Unable to get current capability set: %s\n", - strerror(errno)); - return EX_SYSERR; - } - - if (cap_clear(caps) == -1) { - fprintf(stderr, "Unable to clear capability set: %s\n", - strerror(errno)); - rc = EX_SYSERR; - goto free_caps; - } - - if (parent || getuid() == 0) { - ncap = 1; - cap_list[0] = CAP_DAC_OVERRIDE; - if (parent) { - cap_list[1] = CAP_SYS_ADMIN; - ++ncap; - } - if (cap_set_flag(caps, CAP_PERMITTED, ncap, cap_list, CAP_SET) == -1) { - fprintf(stderr, "Unable to set permitted capabilities: %s\n", - strerror(errno)); - rc = EX_SYSERR; - goto free_caps; - } - if (cap_set_flag(caps, CAP_EFFECTIVE, ncap, cap_list, CAP_SET) == -1) { - fprintf(stderr, "Unable to set effective capabilities: %s\n", - strerror(errno)); - rc = EX_SYSERR; - goto free_caps; - } - } - - if (cap_set_proc(caps) != 0) { - fprintf(stderr, "Unable to set current process capabilities: %s\n", - strerror(errno)); - rc = EX_SYSERR; - } -free_caps: - cap_free(caps); - return rc; -} -#else /* HAVE_LIBCAP */ -static int -drop_capabilities(int parent) -{ - return 0; -} -#endif /* HAVE_LIBCAP */ - /* have the child drop root privileges */ static int drop_child_privs(void) |