static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; u32 ssid, tsid, newsid; u16 tclass; ssize_t length; char *newcon = NULL; u32 len; length = task_has_security(current, SECURITY__COMPUTE_RELABEL); if (length) goto out; length = -ENOMEM; scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) goto out; length = -ENOMEM; tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; length = -EINVAL; if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) goto out; length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length) goto out; length = security_change_sid(ssid, tsid, tclass, &newsid); if (length) goto out; length = security_sid_to_context(newsid, &newcon, &len); if (length) goto out; length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) goto out; memcpy(buf, newcon, len); length = len; out: kfree(newcon); kfree(tcon); kfree(scon); return length; }
int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) { if (selinux_enabled) return security_sid_to_context(sid, ctx, ctxlen); else { *ctx = NULL; *ctxlen = 0; } return 0; }
/** * avc_dump_query - Display a SID pair and a class in human-readable form. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class */ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass) { int rc; char *scontext; u32 scontext_len; rc = security_sid_to_context(ssid, &scontext, &scontext_len); if (rc) audit_log_format(ab, "ssid=%d", ssid); else { audit_log_format(ab, "scontext=%s", scontext); kfree(scontext); } rc = security_sid_to_context(tsid, &scontext, &scontext_len); if (rc) audit_log_format(ab, " tsid=%d", tsid); else { audit_log_format(ab, " tcontext=%s", scontext); kfree(scontext); } audit_log_format(ab, " tclass=%s", class_to_string[tclass]); }
static ssize_t sel_read_initcon(struct file *file, char __user *buf, size_t count, loff_t *ppos) { char *con; u32 sid, len; ssize_t ret; sid = file_inode(file)->i_ino&SEL_INO_MASK; ret = security_sid_to_context(sid, &con, &len); if (ret) return ret; ret = simple_read_from_buffer(buf, count, ppos, con, len); kfree(con); return ret; }
static ssize_t sel_read_initcon(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode; char *con; u32 sid, len; ssize_t ret; inode = file->f_path.dentry->d_inode; sid = inode->i_ino&SEL_INO_MASK; ret = security_sid_to_context(sid, &con, &len); if (ret < 0) return ret; ret = simple_read_from_buffer(buf, count, ppos, con, len); kfree(con); return ret; }
/* * LSM hook implementation that allocates a xfrm_sec_state and populates based * on a secid. */ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) { int rc; struct xfrm_sec_ctx *ctx; char *ctx_str = NULL; int str_len; if (!polsec) return 0; if (secid == 0) return -EINVAL; rc = security_sid_to_context(secid, &ctx_str, &str_len); if (rc) return rc; ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); if (!ctx) { rc = -ENOMEM; goto out; } ctx->ctx_doi = XFRM_SC_DOI_LSM; ctx->ctx_alg = XFRM_SC_ALG_SELINUX; ctx->ctx_sid = secid; ctx->ctx_len = str_len; memcpy(ctx->ctx_str, ctx_str, str_len); x->security = ctx; atomic_inc(&selinux_xfrm_refcount); out: kfree(ctx_str); return rc; }
static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; char *namebuf = NULL, *objname = NULL; u32 ssid, tsid, newsid; u16 tclass; ssize_t length; char *newcon = NULL; u32 len; int nargs; length = task_has_security(current, SECURITY__COMPUTE_CREATE); if (length) goto out; length = -ENOMEM; scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) goto out; length = -ENOMEM; tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; length = -ENOMEM; namebuf = kzalloc(size + 1, GFP_KERNEL); if (!namebuf) goto out; length = -EINVAL; nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf); if (nargs < 3 || nargs > 4) goto out; if (nargs == 4) { /* * If and when the name of new object to be queried contains * either whitespace or multibyte characters, they shall be * encoded based on the percentage-encoding rule. * If not encoded, the sscanf logic picks up only left-half * of the supplied name; splitted by a whitespace unexpectedly. */ char *r, *w; int c1, c2; r = w = namebuf; do { c1 = *r++; if (c1 == '+') c1 = ' '; else if (c1 == '%') { c1 = hex_to_bin(*r++); if (c1 < 0) goto out; c2 = hex_to_bin(*r++); if (c2 < 0) goto out; c1 = (c1 << 4) | c2; } *w++ = c1; } while (c1 != '\0'); objname = namebuf; } length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) goto out; length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length) goto out; length = security_transition_sid_user(ssid, tsid, tclass, objname, &newsid); if (length) goto out; length = security_sid_to_context(newsid, &newcon, &len); if (length) goto out; length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } memcpy(buf, newcon, len); length = len; out: kfree(newcon); kfree(namebuf); kfree(tcon); kfree(scon); return length; }
extern int ps_main(int argc, char **argv) { procps_status_t * p; int i, len; #ifdef CONFIG_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 }; int terminal_width = TERMINAL_WIDTH; #else #define terminal_width TERMINAL_WIDTH #endif #ifdef CONFIG_SELINUX int use_selinux = 0; security_id_t sid; if(is_flask_enabled() && argv[1] && !strcmp(argv[1], "-c") ) use_selinux = 1; #endif #ifdef CONFIG_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_col > 0) terminal_width = win.ws_col - 1; #endif #ifdef CONFIG_SELINUX if(use_selinux) printf(" PID Context Stat Command\n"); else #endif printf(" PID Uid VmSize Stat Command\n"); #ifdef CONFIG_SELINUX while ((p = procps_scan(1, use_selinux, &sid)) != 0) { #else while ((p = procps_scan(1)) != 0) { #endif char *namecmd = p->cmd; #ifdef CONFIG_SELINUX if(use_selinux) { char sbuf[128]; len = sizeof(sbuf); if(security_sid_to_context(sid, (security_context_t)&sbuf, &len)) strcpy(sbuf, "unknown"); len = printf("%5d %-32s %s ", p->pid, sbuf, p->state); } else #endif if(p->rss == 0) len = printf("%5d %-8s %s ", p->pid, p->user, p->state); else len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state); i = terminal_width-len; if(namecmd != 0 && namecmd[0] != 0) { if(i < 0) i = 0; if(strlen(namecmd) > i) namecmd[i] = 0; printf("%s\n", namecmd); } else { namecmd = p->short_cmd; if(i < 2) i = 2; if(strlen(namecmd) > (i-2)) namecmd[i-2] = 0; printf("[%s]\n", namecmd); } free(p->cmd); } return EXIT_SUCCESS; }
/* * Security blob allocation for xfrm_policy and xfrm_state * CTX does not have a meaningful value on input */ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *uctx, u32 sid) { int rc = 0; const struct task_security_struct *tsec = current_security(); struct xfrm_sec_ctx *ctx = NULL; char *ctx_str = NULL; u32 str_len; BUG_ON(uctx && sid); if (!uctx) goto not_from_user; if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX) return -EINVAL; str_len = uctx->ctx_len; if (str_len >= PAGE_SIZE) return -ENOMEM; *ctxp = ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->ctx_doi = uctx->ctx_doi; ctx->ctx_len = str_len; ctx->ctx_alg = uctx->ctx_alg; memcpy(ctx->ctx_str, uctx+1, str_len); ctx->ctx_str[str_len] = 0; rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid); if (rc) goto out; /* * Does the subject have permission to set security context? */ rc = avc_has_perm(tsec->sid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); if (rc) goto out; return rc; not_from_user: rc = security_sid_to_context(sid, &ctx_str, &str_len); if (rc) goto out; *ctxp = ctx = kmalloc(sizeof(*ctx) + str_len, GFP_KERNEL); if (!ctx) { rc = -ENOMEM; goto out; } ctx->ctx_doi = XFRM_SC_DOI_LSM; ctx->ctx_alg = XFRM_SC_ALG_SELINUX; ctx->ctx_sid = sid; ctx->ctx_len = str_len; memcpy(ctx->ctx_str, ctx_str, str_len); goto out2; out: *ctxp = NULL; kfree(ctx); out2: kfree(ctx_str); return rc; }
extern int id_main(int argc, char **argv) { struct passwd *p; uid_t uid; gid_t gid; unsigned long flags; short status; #ifdef CONFIG_SELINUX int is_flask_enabled_flag = is_flask_enabled(); #endif bb_opt_complementaly = "u~g:g~u"; flags = bb_getopt_ulflags(argc, argv, "rnug"); if ((flags & BB_GETOPT_ERROR) /* Don't allow -n -r -nr */ || (flags <= 3 && flags > 0) /* Don't allow more than one username */ || (argc > optind + 1)) bb_show_usage(); /* This values could be overwritten later */ uid = geteuid(); gid = getegid(); if (flags & PRINT_REAL) { uid = getuid(); gid = getgid(); } if(argv[optind]) { p=getpwnam(argv[optind]); /* my_getpwnam is needed because it exits on failure */ uid = my_getpwnam(argv[optind]); gid = p->pw_gid; /* in this case PRINT_REAL is the same */ } if(flags & (JUST_GROUP | JUST_USER)) { /* JUST_GROUP and JUST_USER are mutually exclusive */ if(flags & NAME_NOT_NUMBER) { /* my_getpwuid and my_getgrgid exit on failure so puts cannot segfault */ puts((flags & JUST_USER) ? my_getpwuid(NULL, uid, -1 ) : my_getgrgid(NULL, gid, -1 )); } else { bb_printf("%u\n",(flags & JUST_USER) ? uid : gid); } /* exit */ bb_fflush_stdout_and_exit(EXIT_SUCCESS); } /* Print full info like GNU id */ /* my_getpwuid doesn't exit on failure here */ status=printf_full(uid, my_getpwuid(NULL, uid, 0), 'u'); putchar(' '); /* my_getgrgid doesn't exit on failure here */ status|=printf_full(gid, my_getgrgid(NULL, gid, 0), 'g'); #ifdef CONFIG_SELINUX if(is_flask_enabled_flag) { security_id_t mysid = getsecsid(); char context[80]; int len = sizeof(context); context[0] = '\0'; if(security_sid_to_context(mysid, context, &len)) strcpy(context, "unknown"); bb_printf(" context=%s", context); } #endif putchar('\n'); bb_fflush_stdout_and_exit(status); }
static ssize_t sel_write_user(struct file *file, char *buf, size_t size) { char *con = NULL, *user = NULL, *ptr; u32 sid, *sids = NULL; ssize_t length; char *newcon; int i, rc; u32 len, nsids; char format[32]; length = task_has_security(current, SECURITY__COMPUTE_USER); if (length) goto out; length = -ENOMEM; con = kzalloc(size + 1, GFP_KERNEL); if (!con) goto out; length = -ENOMEM; user = kzalloc(size + 1, GFP_KERNEL); if (!user) goto out; length = -EINVAL; snprintf(format, sizeof(format), "%%%ds %%%ds", size, size); if (sscanf(buf, format, con, user) != 2) goto out; length = security_context_to_sid(con, strlen(con) + 1, &sid); if (length) goto out; length = security_get_user_sids(sid, user, &sids, &nsids); if (length) goto out; length = snprintf(buf, PAGE_SIZE, "%u", nsids) + 1; ptr = buf + length; for (i = 0; i < nsids; i++) { rc = security_sid_to_context(sids[i], &newcon, &len); if (rc) { length = rc; goto out; } if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { kfree(newcon); length = -ERANGE; goto out; } memcpy(ptr, newcon, len); kfree(newcon); ptr += len; length += len; } out: kfree(sids); kfree(user); kfree(con); return length; }
static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; char *namebuf = NULL, *objname = NULL; u32 ssid, tsid, newsid; u16 tclass; ssize_t length; char *newcon = NULL; u32 len; int nargs; char format[32]; length = task_has_security(current, SECURITY__COMPUTE_CREATE); if (length) goto out; length = -ENOMEM; scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) goto out; length = -ENOMEM; tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; length = -ENOMEM; namebuf = kzalloc(size + 1, GFP_KERNEL); if (!namebuf) goto out; length = -EINVAL; snprintf(format, sizeof(format), "%%%ds %%%ds %%hu %%%ds", size, size, size); nargs = sscanf(buf, format, scon, tcon, &tclass, namebuf); if (nargs < 3 || nargs > 4) goto out; if (nargs == 4) { char *r, *w; int c1, c2; r = w = namebuf; do { c1 = *r++; if (c1 == '+') c1 = ' '; else if (c1 == '%') { c1 = hex_to_bin(*r++); if (c1 < 0) goto out; c2 = hex_to_bin(*r++); if (c2 < 0) goto out; c1 = (c1 << 4) | c2; } *w++ = c1; } while (c1 != '\0'); objname = namebuf; } length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) goto out; length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length) goto out; length = security_transition_sid_user(ssid, tsid, tclass, objname, &newsid); if (length) goto out; length = security_sid_to_context(newsid, &newcon, &len); if (length) goto out; length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } memcpy(buf, newcon, len); length = len; out: kfree(newcon); kfree(namebuf); kfree(tcon); kfree(scon); return length; }
extern int id_main(int argc, char **argv) { char user[9], group[9]; long pwnam, grnam; int uid, gid; int flags; #ifdef CONFIG_SELINUX int is_flask_enabled_flag = is_flask_enabled(); #endif flags = bb_getopt_ulflags(argc, argv, "ugrn"); if (((flags & (JUST_USER | JUST_GROUP)) == (JUST_USER | JUST_GROUP)) || (argc > optind + 1) ) { bb_show_usage(); } if (argv[optind] == NULL) { if (flags & PRINT_REAL) { uid = getuid(); gid = getgid(); } else { uid = geteuid(); gid = getegid(); } my_getpwuid(user, uid); } else { safe_strncpy(user, argv[optind], sizeof(user)); gid = my_getpwnamegid(user); } my_getgrgid(group, gid); pwnam=my_getpwnam(user); grnam=my_getgrnam(group); if (flags & (JUST_GROUP | JUST_USER)) { char *s = group; if (flags & JUST_USER) { s = user; grnam = pwnam; } if (flags & NAME_NOT_NUMBER) { puts(s); } else { printf("%ld\n", grnam); } } else { #ifdef CONFIG_SELINUX printf("uid=%ld(%s) gid=%ld(%s)", pwnam, user, grnam, group); if(is_flask_enabled_flag) { security_id_t mysid = getsecsid(); char context[80]; int len = sizeof(context); context[0] = '\0'; if(security_sid_to_context(mysid, context, &len)) strcpy(context, "unknown"); printf(" context=%s\n", context); } else printf("\n"); #else printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group); #endif } bb_fflush_stdout_and_exit(0); }
/*----------------------------------------------------------------------*/ static int list_single(struct dnode *dn) { int i, column = 0; #ifdef CONFIG_FEATURE_LS_USERNAME char scratch[16]; #endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS char *filetime; time_t ttime, age; #endif #if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR) struct stat info; char append; #endif if (dn->fullname == NULL) return (0); #ifdef CONFIG_FEATURE_LS_TIMESTAMPS ttime = dn->dstat.st_mtime; /* the default time */ if (all_fmt & TIME_ACCESS) ttime = dn->dstat.st_atime; if (all_fmt & TIME_CHANGE) ttime = dn->dstat.st_ctime; filetime = ctime(&ttime); #endif #ifdef CONFIG_FEATURE_LS_FILETYPES append = append_char(dn->dstat.st_mode); #endif for (i = 0; i <= 31; i++) { switch (all_fmt & (1 << i)) { case LIST_INO: column += printf("%7ld ", (long int) dn->dstat.st_ino); break; case LIST_BLOCKS: #if _FILE_OFFSET_BITS == 64 column += printf("%4lld ", dn->dstat.st_blocks >> 1); #else column += printf("%4ld ", dn->dstat.st_blocks >> 1); #endif break; case LIST_MODEBITS: column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode)); break; case LIST_NLINKS: column += printf("%4ld ", (long) dn->dstat.st_nlink); break; case LIST_ID_NAME: #ifdef CONFIG_FEATURE_LS_USERNAME my_getpwuid(scratch, dn->dstat.st_uid); printf("%-8.8s ", scratch); my_getgrgid(scratch, dn->dstat.st_gid); printf("%-8.8s", scratch); column += 17; break; #endif case LIST_ID_NUMERIC: column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid); break; case LIST_SIZE: case LIST_DEV: if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { column += printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev), (int) MINOR(dn->dstat.st_rdev)); } else { #ifdef CONFIG_FEATURE_HUMAN_READABLE if (all_fmt & LS_DISP_HR) { column += printf("%9s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); } else #endif { #if _FILE_OFFSET_BITS == 64 column += printf("%9lld ", (long long) dn->dstat.st_size); #else column += printf("%9ld ", dn->dstat.st_size); #endif } } break; #ifdef CONFIG_FEATURE_LS_TIMESTAMPS case LIST_FULLTIME: printf("%24.24s ", filetime); column += 25; break; case LIST_DATE_TIME: if ((all_fmt & LIST_FULLTIME) == 0) { age = time(NULL) - ttime; printf("%6.6s ", filetime + 4); if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { /* hh:mm if less than 6 months old */ printf("%5.5s ", filetime + 11); } else { printf(" %4.4s ", filetime + 20); } column += 13; } break; #endif #ifdef CONFIG_SELINUX case LIST_CONTEXT: { char context[64]; int len = sizeof(context); if(security_sid_to_context(dn->sid, context, &len)) { strcpy(context, "unknown"); len = 7; } printf("%-32s ", context); column += MAX(33, len); } break; #endif case LIST_FILENAME: #ifdef CONFIG_FEATURE_LS_COLOR errno = 0; if (show_color && !lstat(dn->fullname, &info)) { printf("\033[%d;%dm", bgcolor(info.st_mode), fgcolor(info.st_mode)); } #endif column += printf("%s", dn->name); #ifdef CONFIG_FEATURE_LS_COLOR if (show_color) { printf("\033[0m"); } #endif break; case LIST_SYMLINK: if (S_ISLNK(dn->dstat.st_mode)) { char *lpath = xreadlink(dn->fullname); if (lpath) { printf(" -> "); #if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR) if (!stat(dn->fullname, &info)) { append = append_char(info.st_mode); } #endif #ifdef CONFIG_FEATURE_LS_COLOR if (show_color) { errno = 0; printf("\033[%d;%dm", bgcolor(info.st_mode), fgcolor(info.st_mode)); } #endif column += printf("%s", lpath) + 4; #ifdef CONFIG_FEATURE_LS_COLOR if (show_color) { printf("\033[0m"); } #endif free(lpath); } } break; #ifdef CONFIG_FEATURE_LS_FILETYPES case LIST_FILETYPE: if (append != '\0') { printf("%1c", append); column++; } break; #endif } } return column; }
static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; char *namebuf = NULL, *objname = NULL; u32 ssid, tsid, newsid; u16 tclass; ssize_t length; char *newcon = NULL; u32 len; int nargs; length = task_has_security(current, SECURITY__COMPUTE_CREATE); if (length) goto out; length = -ENOMEM; scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) goto out; length = -ENOMEM; tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; length = -ENOMEM; namebuf = kzalloc(size + 1, GFP_KERNEL); if (!namebuf) goto out; length = -EINVAL; nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf); if (nargs < 3 || nargs > 4) goto out; if (nargs == 4) objname = namebuf; length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) goto out; length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length) goto out; length = security_transition_sid_user(ssid, tsid, tclass, objname, &newsid); if (length) goto out; length = security_sid_to_context(newsid, &newcon, &len); if (length) goto out; length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } memcpy(buf, newcon, len); length = len; out: kfree(newcon); kfree(namebuf); kfree(tcon); kfree(scon); return length; }
static ssize_t sel_write_user(struct file *file, char *buf, size_t size) { char *con = NULL, *user = NULL, *ptr; u32 sid, *sids = NULL; ssize_t length; char *newcon; int i, rc; u32 len, nsids; length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_USER, NULL); if (length) goto out; length = -ENOMEM; con = kzalloc(size + 1, GFP_KERNEL); if (!con) goto out; length = -ENOMEM; user = kzalloc(size + 1, GFP_KERNEL); if (!user) goto out; length = -EINVAL; if (sscanf(buf, "%s %s", con, user) != 2) goto out; length = security_context_str_to_sid(con, &sid, GFP_KERNEL); if (length) goto out; length = security_get_user_sids(sid, user, &sids, &nsids); if (length) goto out; length = sprintf(buf, "%u", nsids) + 1; ptr = buf + length; for (i = 0; i < nsids; i++) { rc = security_sid_to_context(sids[i], &newcon, &len); if (rc) { length = rc; goto out; } if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { kfree(newcon); length = -ERANGE; goto out; } memcpy(ptr, newcon, len); kfree(newcon); ptr += len; length += len; } out: kfree(sids); kfree(user); kfree(con); return length; }