Loading security/selinux/hooks.c +54 −92 Original line number Diff line number Diff line Loading @@ -2606,109 +2606,71 @@ static void selinux_sb_free_security(struct super_block *sb) superblock_free_security(sb); } static inline int match_prefix(char *prefix, int plen, char *option, int olen) static inline int opt_len(const char *s) { if (plen > olen) return 0; bool open_quote = false; int len; char c; return !memcmp(prefix, option, plen); for (len = 0; (c = s[len]) != '\0'; len++) { if (c == '"') open_quote = !open_quote; if (c == ',' && !open_quote) break; } static inline int selinux_option(char *option, int len) { return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); return len; } static inline void take_option(char **to, char *from, int *first, int len) static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) { if (!*first) { **to = ','; *to += 1; } else *first = 0; memcpy(*to, from, len); *to += len; } char *from = options; char *to = options; bool first = true; static inline void take_selinux_option(char **to, char *from, int *first, int len) { int current_size = 0; while (1) { int len = opt_len(from); int token, rc; char *arg = NULL; if (!*first) { **to = '|'; *to += 1; } else *first = 0; token = match_opt_prefix(from, len, &arg); if (token != Opt_error) { char *p, *q; while (current_size < len) { if (*from != '"') { **to = *from; *to += 1; /* strip quotes */ if (arg) { for (p = q = arg; p < from + len; p++) { char c = *p; if (c != '"') *q++ = c; } from += 1; current_size += 1; arg = kmemdup_nul(arg, q - arg, GFP_KERNEL); } rc = selinux_add_opt(token, arg, mnt_opts); if (unlikely(rc)) { kfree(arg); if (*mnt_opts) { selinux_free_mnt_opts(*mnt_opts); *mnt_opts = NULL; } static int selinux_sb_copy_data(char *orig, char *copy) { int fnosec, fsec, rc = 0; char *in_save, *in_curr, *in_end; char *sec_curr, *nosec_save, *nosec; int open_quote = 0; in_curr = orig; sec_curr = copy; nosec = (char *)get_zeroed_page(GFP_KERNEL); if (!nosec) { rc = -ENOMEM; goto out; return rc; } nosec_save = nosec; fnosec = fsec = 1; in_save = in_end = orig; do { if (*in_end == '"') open_quote = !open_quote; if ((*in_end == ',' && open_quote == 0) || *in_end == '\0') { int len = in_end - in_curr; if (selinux_option(in_curr, len)) take_selinux_option(&sec_curr, in_curr, &fsec, len); else take_option(&nosec, in_curr, &fnosec, len); in_curr = in_end + 1; } else { if (!first) { // copy with preceding comma from--; len++; } } while (*in_end++); strcpy(in_save, nosec_save); free_page((unsigned long)nosec_save); out: return rc; if (to != from) memmove(to, from, len); to += len; first = false; } static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) { char *s = (char *)get_zeroed_page(GFP_KERNEL); int err; if (!s) return -ENOMEM; err = selinux_sb_copy_data(options, s); if (!err) err = selinux_parse_opts_str(s, mnt_opts); free_page((unsigned long)s); return err; if (!from[len]) break; from += len + 1; } *to = '\0'; return 0; } static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) Loading Loading
security/selinux/hooks.c +54 −92 Original line number Diff line number Diff line Loading @@ -2606,109 +2606,71 @@ static void selinux_sb_free_security(struct super_block *sb) superblock_free_security(sb); } static inline int match_prefix(char *prefix, int plen, char *option, int olen) static inline int opt_len(const char *s) { if (plen > olen) return 0; bool open_quote = false; int len; char c; return !memcmp(prefix, option, plen); for (len = 0; (c = s[len]) != '\0'; len++) { if (c == '"') open_quote = !open_quote; if (c == ',' && !open_quote) break; } static inline int selinux_option(char *option, int len) { return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); return len; } static inline void take_option(char **to, char *from, int *first, int len) static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) { if (!*first) { **to = ','; *to += 1; } else *first = 0; memcpy(*to, from, len); *to += len; } char *from = options; char *to = options; bool first = true; static inline void take_selinux_option(char **to, char *from, int *first, int len) { int current_size = 0; while (1) { int len = opt_len(from); int token, rc; char *arg = NULL; if (!*first) { **to = '|'; *to += 1; } else *first = 0; token = match_opt_prefix(from, len, &arg); if (token != Opt_error) { char *p, *q; while (current_size < len) { if (*from != '"') { **to = *from; *to += 1; /* strip quotes */ if (arg) { for (p = q = arg; p < from + len; p++) { char c = *p; if (c != '"') *q++ = c; } from += 1; current_size += 1; arg = kmemdup_nul(arg, q - arg, GFP_KERNEL); } rc = selinux_add_opt(token, arg, mnt_opts); if (unlikely(rc)) { kfree(arg); if (*mnt_opts) { selinux_free_mnt_opts(*mnt_opts); *mnt_opts = NULL; } static int selinux_sb_copy_data(char *orig, char *copy) { int fnosec, fsec, rc = 0; char *in_save, *in_curr, *in_end; char *sec_curr, *nosec_save, *nosec; int open_quote = 0; in_curr = orig; sec_curr = copy; nosec = (char *)get_zeroed_page(GFP_KERNEL); if (!nosec) { rc = -ENOMEM; goto out; return rc; } nosec_save = nosec; fnosec = fsec = 1; in_save = in_end = orig; do { if (*in_end == '"') open_quote = !open_quote; if ((*in_end == ',' && open_quote == 0) || *in_end == '\0') { int len = in_end - in_curr; if (selinux_option(in_curr, len)) take_selinux_option(&sec_curr, in_curr, &fsec, len); else take_option(&nosec, in_curr, &fnosec, len); in_curr = in_end + 1; } else { if (!first) { // copy with preceding comma from--; len++; } } while (*in_end++); strcpy(in_save, nosec_save); free_page((unsigned long)nosec_save); out: return rc; if (to != from) memmove(to, from, len); to += len; first = false; } static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) { char *s = (char *)get_zeroed_page(GFP_KERNEL); int err; if (!s) return -ENOMEM; err = selinux_sb_copy_data(options, s); if (!err) err = selinux_parse_opts_str(s, mnt_opts); free_page((unsigned long)s); return err; if (!from[len]) break; from += len + 1; } *to = '\0'; return 0; } static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) Loading