diff options
author | Elliott Hughes <enh@google.com> | 2015-05-30 13:22:56 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2015-05-30 13:22:56 -0700 |
commit | 8bdb32495fe8f0a038fe0ac02905dc4f2d8c660b (patch) | |
tree | 49e568a3f7f35af6cee0f921757b811c0bdc9732 | |
parent | 632d81c469358ec4f41a90474dcf93326839438a (diff) | |
parent | 2d66e6a23822a500ecf6610411941e99127129c8 (diff) | |
download | toybox-8bdb32495fe8f0a038fe0ac02905dc4f2d8c660b.tar.gz |
Merge remote-tracking branch 'toybox/master' into HEAD
-rw-r--r-- | lib/lsm.h | 115 | ||||
-rw-r--r-- | lib/portability.h | 25 | ||||
-rw-r--r-- | toys.h | 1 | ||||
-rw-r--r-- | toys/other/stat.c | 2 | ||||
-rw-r--r-- | toys/posix/grep.c | 8 | ||||
-rw-r--r-- | toys/posix/id.c | 53 | ||||
-rw-r--r-- | toys/posix/ls.c | 125 | ||||
-rw-r--r-- | toys/posix/mkdir.c | 19 |
8 files changed, 224 insertions, 124 deletions
diff --git a/lib/lsm.h b/lib/lsm.h new file mode 100644 index 00000000..d7e7de9c --- /dev/null +++ b/lib/lsm.h @@ -0,0 +1,115 @@ +/* lsm.h - header file for lib directory + * + * Copyright 2015 Rob Landley <rob@landley.net> + */ + +#if CFG_TOYBOX_SELINUX +#include <selinux/selinux.h> +#else +#define is_selinux_enabled() 0 +#define setfscreatecon(...) (-1) +#define getcon(...) (-1) +#define getfilecon(...) (-1) +#define lgetfilecon(...) (-1) +#define fgetfilecon(...) (-1) +#define setfilecon(...) (-1) +#define lsetfilecon(...) (-1) +#define fsetfilecon(...) (-1) +#endif + +#if CFG_TOYBOX_SMACK +#include <sys/smack.h> +#include <sys/xattr.h> +#include <linux/xattr.h> +#else +#define XATTR_NAME_SMACK 0 +//ssize_t fgetxattr (int fd, char *name, void *value, size_t size); +#define smack_smackfs_path(...) (-1) +#define smack_new_label_from_self(...) (-1) +#define smack_new_label_from_path(...) (-1) +#define smack_new_label_from_file(...) (-1) +#define smack_set_label_for_self(...) (-1) +#define smack_set_label_for_path(...) (-1) +#define smack_set_label_for_file(...) (-1) +#endif + +// This turns into "return 0" when no LSM and lets code optimize out. +static inline int lsm_enabled(void) +{ + if (CFG_TOYBOX_SMACK) return !!smack_smackfs_path(); + else return is_selinux_enabled() == 1; +} + +static inline char *lsm_name(void) +{ + if (CFG_TOYBOX_SMACK) return "Smack"; + if (CFG_TOYBOX_SELINUX) return "SELinux"; + + return "LSM"; +} + +// Fetch this process's lsm context +static inline char *lsm_context(void) +{ + int ok = 0; + char *result; + + if (CFG_TOYBOX_SMACK) ok = smack_new_label_from_self(&result) > 0; + else ok = getcon(&result) == 0; + + return ok ? result : strdup("?"); +} + +// Set default label to apply to newly created stuff (NULL to clear it) +static inline int lsm_set_create(char *context) +{ + if (CFG_TOYBOX_SMACK) return smack_set_label_for_self(context); + else return setfscreatecon(context); +} + +// Label a file, following symlinks +static inline int lsm_set_context(char *filename, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_path(filename, XATTR_NAME_SMACK, 1, context); + else return setfilecon(filename, context); +} + +// Label a file, don't follow symlinks +static inline int lsm_lset_context(char *filename, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_path(filename, XATTR_NAME_SMACK, 0, context); + else return lsetfilecon(filename, context); +} + +// Label a file by filehandle +static inline int lsm_fset_context(int file, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_file(file, XATTR_NAME_SMACK, context); + else return fsetfilecon(file, context); +} + +// returns -1 in case of error or else the length of the context */ +// context can be NULL to get the length only */ +static inline int lsm_get_context(char *filename, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_path(filename, XATTR_NAME_SMACK, 1, context); + else return getfilecon(filename, context); +} + +static inline int lsm_lget_context(char *filename, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_path(filename, XATTR_NAME_SMACK, 0, context); + else return lgetfilecon(filename, context); +} + +static inline int lsm_fget_context(int file, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_file(file, XATTR_NAME_SMACK, context); + return fgetfilecon(file, context); +} diff --git a/lib/portability.h b/lib/portability.h index aa1ee488..f83cab60 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -225,6 +225,10 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #define O_NOFOLLOW 0 #endif +#ifndef O_NOATIME +#define O_NOATIME 01000000 +#endif + #ifndef O_CLOEXEC #define O_CLOEXEC 02000000 #endif @@ -247,24 +251,3 @@ pid_t xfork(void); //#define strncpy(...) @@strncpyisbadmmkay@@ //#define strncat(...) @@strncatisbadmmkay@@ -#if CFG_TOYBOX_SELINUX -#include <selinux/selinux.h> -#else -#define is_selinux_enabled() 0 -int getcon(void* con); -#endif - -#if CFG_TOYBOX_SMACK -#include <sys/smack.h> -#include <sys/xattr.h> -#include <linux/xattr.h> -#else -#define smack_new_label_from_path(...) (-1) -#define smack_set_label_for_path(...) (-1) -#define smack_set_label_for_self(...) (-1) -#define XATTR_NAME_SMACK "" -#define SMACK_LABEL_LEN (1) /* for just ? */ - -ssize_t fgetxattr (int fd, char *name, void *value, size_t size); -#endif - @@ -68,6 +68,7 @@ #include <sys/sysinfo.h> #include "lib/lib.h" +#include "lib/lsm.h" #include "toys/e2fs.h" // Get list of function prototypes for all enabled command_main() functions. diff --git a/toys/other/stat.c b/toys/other/stat.c index a96c1def..d6db44dd 100644 --- a/toys/other/stat.c +++ b/toys/other/stat.c @@ -82,7 +82,7 @@ static void print_stat(char type) if (!stat->st_size && filetype == S_IFREG) t = "regular empty file"; xprintf("%s", t); } else if (type == 'g') xprintf("%lu", stat->st_gid); - else if (type == 'G') xprintf("%8s", TT.user_name->pw_name); + else if (type == 'G') xprintf("%8s", TT.group_name->gr_name); else if (type == 'h') xprintf("%lu", stat->st_nlink); else if (type == 'i') xprintf("%llu", stat->st_ino); else if (type == 'N') { diff --git a/toys/posix/grep.c b/toys/posix/grep.c index 61df08ea..6e383efc 100644 --- a/toys/posix/grep.c +++ b/toys/posix/grep.c @@ -269,7 +269,7 @@ static int do_grep_r(struct dirtree *new) void grep_main(void) { - char **ss; + char **ss = toys.optargs; // Handle egrep and fgrep if (*toys.which->name == 'e' || (toys.optflags & FLAG_w)) @@ -277,9 +277,9 @@ void grep_main(void) if (*toys.which->name == 'f') toys.optflags |= FLAG_F; if (!TT.e && !TT.f) { - if (!*toys.optargs) error_exit("no REGEX"); + if (!*ss) error_exit("no REGEX"); TT.e = xzalloc(sizeof(struct arg_list)); - TT.e->arg = *(toys.optargs++); + TT.e->arg = *(ss++); toys.optc--; } @@ -294,7 +294,7 @@ void grep_main(void) } if (toys.optflags & FLAG_r) { - for (ss=toys.optargs; *ss; ss++) { + for (ss = *ss ? ss : (char *[]){".", 0}; *ss; ss++) { if (!strcmp(*ss, "-")) do_grep(0, *ss); else dirtree_read(*ss, do_grep_r); } diff --git a/toys/posix/id.c b/toys/posix/id.c index 7ab489ef..aa43072f 100644 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -6,7 +6,7 @@ * * See http://opengroup.org/onlinepubs/9699919799/utilities/id.html -USE_ID(NEWTOY(id, ">1"USE_ID_SELINUX("Z")"nGgru[!"USE_ID_SELINUX("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_ID(NEWTOY(id, ">1"USE_ID_Z("Z")"nGgru[!"USE_ID_Z("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN)) USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN)) USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN)) USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN)) @@ -25,14 +25,14 @@ config ID -r Show real ID instead of effective ID -u Show only the effective user ID -config ID_SELINUX +config ID_Z bool default y - depends on ID && TOYBOX_SELINUX + depends on ID && !TOYBOX_LSM_NONE help usage: id [-Z] - -Z Show only SELinux context + -Z Show only security context config GROUPS bool "groups" @@ -60,15 +60,16 @@ config WHOAMI */ #define FOR_id +#define FORCE_FLAGS #include "toys.h" GLOBALS( - int do_u, do_n, do_G, do_Z, is_groups; + int is_groups; ) static void s_or_u(char *s, unsigned u, int done) { - if (TT.do_n) printf("%s", s); + if (toys.optflags&FLAG_n) printf("%s", s); else printf("%u", u); if (done) { xputc('\n'); @@ -101,12 +102,12 @@ void do_id(char *username) i = flags & FLAG_r; pw = xgetpwuid(i ? uid : euid); - if (TT.do_u) s_or_u(pw->pw_name, pw->pw_uid, 1); + if (toys.optflags&FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); grp = xgetgrgid(i ? gid : egid); if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); - if (!TT.do_G && !TT.do_Z) { + if (!(toys.optflags&(FLAG_g|FLAG_Z))) { showid("uid=", pw->pw_uid, pw->pw_name); showid(" gid=", grp->gr_gid, grp->gr_name); @@ -124,39 +125,35 @@ void do_id(char *username) showid(" groups=", grp->gr_gid, grp->gr_name); } - if (!TT.do_Z) { + if (!(toys.optflags&FLAG_Z)) { groups = (gid_t *)toybuf; i = sizeof(toybuf)/sizeof(gid_t); ngroups = username ? getgrouplist(username, gid, groups, &i) : getgroups(i, groups); if (ngroups<0) perror_exit(0); - int show_separator = !TT.do_G; + int show_separator = !(toys.optflags&FLAG_G); for (i = 0; i<ngroups; i++) { - if (show_separator) xputc(TT.do_G ? ' ' : ','); + if (show_separator) xputc((toys.optflags&FLAG_G) ? ' ' : ','); show_separator = 1; if (!(grp = getgrgid(groups[i]))) perror_msg(0); - else if (TT.do_G) s_or_u(grp->gr_name, grp->gr_gid, 0); + else if (toys.optflags&FLAG_G) s_or_u(grp->gr_name, grp->gr_gid, 0); else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); else show_separator = 0; // Because we didn't show anything this time. } - if (TT.do_G) { + if (toys.optflags&FLAG_G) { xputc('\n'); exit(0); } } - if (CFG_TOYBOX_SELINUX) { - char *context = NULL; + if (!CFG_TOYBOX_LSM_NONE) { + if (lsm_enabled()) { + char *context = lsm_context(); - if (is_selinux_enabled() < 1) { - if (TT.do_Z) - error_exit("SELinux disabled"); - } else if (getcon(&context) == 0) { - if (!TT.do_Z) xputc(' '); - printf("context=%s", context); - } - if (CFG_TOYBOX_FREE) free(context); + printf(" context=%s"+!!(toys.optflags&FLAG_Z), context); + if (CFG_TOYBOX_FREE) free(context); + } else if (toys.optflags&FLAG_Z) error_exit("%s disabled", lsm_name()); } xputc('\n'); @@ -164,12 +161,6 @@ void do_id(char *username) void id_main(void) { - // FLAG macros can be 0 if "id" command not enabled, so snapshot them here. - if (FLAG_u) TT.do_u |= toys.optflags & FLAG_u; - if (FLAG_n) TT.do_n |= toys.optflags & FLAG_n; - if (FLAG_G) TT.do_G |= toys.optflags & FLAG_G; - if (FLAG_Z) TT.do_Z |= toys.optflags & FLAG_Z; - if (toys.optc) while(*toys.optargs) do_id(*toys.optargs++); else do_id(NULL); } @@ -177,12 +168,12 @@ void id_main(void) void groups_main(void) { TT.is_groups = 1; - TT.do_G = TT.do_n = 1; + toys.optflags = FLAG_G|FLAG_n; id_main(); } void logname_main(void) { - TT.do_u = TT.do_n = 1; + toys.optflags = FLAG_u|FLAG_n; id_main(); } diff --git a/toys/posix/ls.c b/toys/posix/ls.c index 35d1034a..15796ff1 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -5,13 +5,13 @@ * * See http://opengroup.org/onlinepubs/9699919799/utilities/ls.html -USE_LS(NEWTOY(ls, USE_LS_COLOR("(color):;")USE_LS_Z("Z")"goACFHLRSacdfiklmnpqrstux1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL]", TOYFLAG_BIN|TOYFLAG_LOCALE)) +USE_LS(NEWTOY(ls, USE_LS_COLOR("(color):;")"ZgoACFHLRSacdfiklmnpqrstux1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL]", TOYFLAG_BIN|TOYFLAG_LOCALE)) config LS bool "ls" default y help - usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] + usage: ls [-ACFHLRSZacdfiklmnpqrstux1] [directory...] list files what to show: @@ -22,6 +22,7 @@ config LS -u use access time for timestamps -A list all files but . and .. -H follow command line symlinks -L follow symlinks -R recursively list files in subdirs -F append /dir *exe @sym |FIFO + -Z security context output formats: -1 list one file per line -C columns (sorted vertically) @@ -32,15 +33,6 @@ config LS sorting (default is alphabetical): -f unsorted -r reverse -t timestamp -S size -config LS_Z - bool - default y - depends on LS && (TOYBOX_SELINUX || TOYBOX_SMACK) - help - usage: ls [-Z] - - -Z security context - config LS_COLOR bool "ls --color" default y @@ -63,7 +55,7 @@ config LS_COLOR GLOBALS( char *color; - struct dirtree *files; + struct dirtree *files, *singledir; unsigned screen_width; int nl_title; @@ -129,44 +121,6 @@ static int numlen(long long ll) return snprintf(0, 0, "%llu", ll); } -// measure/print SELinux/smack security label. (If pad=0, just measure.) -static unsigned seclabel(struct dirtree *dt, int pad) -{ - if (CFG_TOYBOX_SELINUX) { - char* path = dirtree_path(dt, 0); - char* label = 0; - size_t len; - - lgetfilecon(path, &label); - if (!label) { - label = strdup("?"); - } - - len = strlen(label); - if (pad) printf(" %*s "+(pad>0), pad, label); - - free(label); - free(path); - return len; - } else if (CFG_TOYBOX_SMACK) { - int fd = openat(dirtree_parentfd(dt), dt->name, O_PATH|O_NOFOLLOW); - char buf[SMACK_LABEL_LEN+1]; - ssize_t len = 1; - - strcpy(buf, "?"); - if (fd != -1) { - len = fgetxattr(fd, XATTR_NAME_SMACK, pad?buf:0, pad?SMACK_LABEL_LEN:0); - close(fd); - - if (len<1 || len>SMACK_LABEL_LEN) len = 0; - else buf[len] = 0; - } - if (pad) printf(" %*s "+(pad>0), pad, buf); - - return len; - } -} - // Figure out size of printable entry fields for display indent/wrap static void entrylen(struct dirtree *dt, unsigned *len) @@ -192,7 +146,7 @@ static void entrylen(struct dirtree *dt, unsigned *len) } len[6] = (flags & FLAG_s) ? numlen(st->st_blocks) : 0; - len[7] = (CFG_LS_Z && (flags & FLAG_Z)) ? seclabel(dt, 0) : 0; + len[7] = (flags & FLAG_Z) ? strwidth((char *)dt->extra) : 0; } static int compare(void *a, void *b) @@ -225,6 +179,42 @@ static int filter(struct dirtree *new) return 0; } + if (flags & FLAG_Z) { + if (!CFG_TOYBOX_LSM_NONE) { + int fd; + + // Why not just openat(O_PATH|(O_NOFOLLOW*!!(toys.optflags&FLAG_L))) and + // lsm_fget_context() on that filehandle? Because the kernel is broken, + // and won't let us read this "metadata" from the filehandle unless we + // have permission to read the data. We _can_ read the same data in + // by path, we just can't do it through an O_PATH filehandle, because + // reasons. So as a bug workaround for the broken kernel, we do it + // both ways. + // + // The O_NONBLOCK is there to avoid triggering automounting (there's + // a rush of nostalgia for you) on directories we don't descend into, + // which O_PATH would have done for us but see "the kernel is broken". + if (S_ISSOCK(new->st.st_mode) || + (S_ISLNK(new->st.st_mode) && !(toys.optflags & FLAG_L)) || + -1 == (fd = openat(dirtree_parentfd(new), new->name, + O_RDONLY|O_NONBLOCK|O_NOATIME))) + { + char *path; + + // Wouldn't it be nice if the lsm functions worked like openat(), + // fchmodat(), mknodat(), readlinkat() so we could do this without + // even O_PATH? But no, this is 1990's tech. + path = dirtree_path(new, 0); + lsm_lget_context(path, (char **)&new->extra); + free(path); + } else { + lsm_fget_context(fd, (char **)&new->extra); + close(fd); + } + } + if (CFG_TOYBOX_LSM_NONE || !new->extra) new->extra = (long)xstrdup("?"); + } + if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; @@ -303,18 +293,23 @@ static void listfiles(int dirfd, struct dirtree *indir) memset(totals, 0, sizeof(totals)); - // Silently descend into single directory listed by itself on command line. - // In this case only show dirname/total header when given -R. + // Top level directory was already populated by main() if (!indir->parent) { - if (!(dt = indir->child)) return; - if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { - dt->extra = 1; - listfiles(open(dt->name, 0), dt); + // Silently descend into single directory listed by itself on command line. + // In this case only show dirname/total header when given -R. + dt = indir->child; + if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags&(FLAG_d|FLAG_R))) { + listfiles(open(dt->name, 0), TT.singledir = dt); return; } + + // Do preprocessing (Dirtree didn't populate, so callback wasn't called.) + for (;dt; dt = dt->next) filter(dt); + if (flags == (FLAG_1|FLAG_f)) return; } else { // Read directory contents. We dup() the fd because this will close it. + // This reads/saves contents to display later, except for in "ls -1f" mode. indir->data = dup(dirfd); dirtree_recurse(indir, filter, DIRTREE_SYMFOLLOW*!!(flags&FLAG_L)); } @@ -329,7 +324,7 @@ static void listfiles(int dirfd, struct dirtree *indir) } // Label directory if not top of tree, or if -R - if (indir->parent && (!indir->extra || (flags & FLAG_R))) + if (indir->parent && (TT.singledir!=indir || (flags&FLAG_R))) { char *path = dirtree_path(indir, 0); @@ -350,7 +345,7 @@ static void listfiles(int dirfd, struct dirtree *indir) blocks += sort[ul]->st.st_blocks; } totpad = totals[1]+!!totals[1]+totals[6]+!!totals[6]+totals[7]+!!totals[7]; - if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s) && indir->parent) + if ((flags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) && indir->parent) xprintf("total %llu\n", blocks); } @@ -442,7 +437,8 @@ static void listfiles(int dirfd, struct dirtree *indir) printf("%s% *ld %s%s%s%s", perm, totals[2]+1, (long)st->st_nlink, usr, upad, grp, grpad); - if (CFG_LS_Z && (flags & FLAG_Z)) seclabel(sort[next], -(int)totals[7]); + if (flags & FLAG_Z) + printf(" %*s ", -(int)totals[7], (char *)sort[next]->extra); if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) printf("% *d,% 4d", totals[5]-4, major(st->st_rdev),minor(st->st_rdev)); @@ -451,7 +447,8 @@ static void listfiles(int dirfd, struct dirtree *indir) tm = localtime(&(st->st_mtime)); strftime(thyme, sizeof(thyme), "%F %H:%M", tm); xprintf(" %s ", thyme); - } else if (CFG_LS_Z && (flags & FLAG_Z)) seclabel(sort[next], totals[7]); + } else if (flags & FLAG_Z) + printf("%*s ", (int)totals[7], (char *)sort[next]->extra); if (flags & FLAG_color) { color = color_from_mode(st->st_mode); @@ -493,12 +490,12 @@ static void listfiles(int dirfd, struct dirtree *indir) // Free directory entries, recursing first if necessary. for (ul = 0; ul<dtlen; free(sort[ul++])) { - if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) - || !dirtree_notdotdot(sort[ul])) continue; + if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode)) continue; // Recurse into dirs if at top of the tree or given -R - if (!indir->parent || (flags & FLAG_R)) + if (!indir->parent || ((flags&FLAG_R) && dirtree_notdotdot(sort[ul]))) listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); + free((void *)sort[ul]->extra); } free(sort); if (dirfd != AT_FDCWD) close(dirfd); diff --git a/toys/posix/mkdir.c b/toys/posix/mkdir.c index 739f961b..438e38ea 100644 --- a/toys/posix/mkdir.c +++ b/toys/posix/mkdir.c @@ -4,7 +4,7 @@ * * See http://opengroup.org/onlinepubs/9699919799/utilities/mkdir.html -USE_MKDIR(NEWTOY(mkdir, "<1vpm:", TOYFLAG_BIN|TOYFLAG_UMASK)) +USE_MKDIR(NEWTOY(mkdir, "<1"USE_MKDIR_Z("Z:")"vpm:", TOYFLAG_BIN|TOYFLAG_UMASK)) config MKDIR bool "mkdir" @@ -17,6 +17,15 @@ config MKDIR -m set permissions of directory to mode. -p make parent directories as needed. -v verbose + +config MKDIR_Z + bool + default y + depends on MKDIR && !TOYBOX_LSM_NONE + help + usage: [-Z context] + + -Z set security context */ #define FOR_mkdir @@ -24,6 +33,7 @@ config MKDIR GLOBALS( char *arg_mode; + char *arg_context; ) void mkdir_main(void) @@ -31,12 +41,15 @@ void mkdir_main(void) char **s; mode_t mode = (0777&~toys.old_umask); + if (CFG_MKDIR_Z && (toys.optflags&FLAG_Z)) + if (0>lsm_set_create(TT.arg_context)) + error_exit("bad -Z '%s'", TT.arg_context); if (TT.arg_mode) mode = string_to_mode(TT.arg_mode, 0777); // Note, -p and -v flags line up with mkpathat() flags - - for (s=toys.optargs; *s; s++) + for (s=toys.optargs; *s; s++) { if (mkpathat(AT_FDCWD, *s, mode, toys.optflags|1)) perror_msg("'%s'", *s); + } } |