/* * AppArmor security module * * This file contains AppArmor /proc//attr/ interface functions * * Copyright (C) 1998-2008 Novell/SUSE * Copyright 2009-2010 Canonical Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. */ #include "include/apparmor.h" #include "include/context.h" #include "include/policy.h" #include "include/domain.h" #include "include/procattr.h" /** * aa_getprocattr - Return the profile information for @profile * @profile: the profile to print profile info about (NOT NULL) * @string: Returns - string containing the profile info (NOT NULL) * * Returns: length of @string on success else error on failure * * Requires: profile != NULL * * Creates a string containing the namespace_name://profile_name for * @profile. * * Returns: size of string placed in @string else error code on failure */ int aa_getprocattr(struct aa_profile *profile, char **string) { char *str; int len = 0, mode_len = 0, ns_len = 0, name_len; const char *mode_str = aa_profile_mode_names[profile->mode]; const char *ns_name = NULL; struct aa_namespace *ns = profile->ns; struct aa_namespace *current_ns = __aa_current_profile()->ns; char *s; if (!aa_ns_visible(current_ns, ns)) return -EACCES; ns_name = aa_ns_name(current_ns, ns); ns_len = strlen(ns_name); /* if the visible ns_name is > 0 increase size for : :// seperator */ if (ns_len) ns_len += 4; /* unconfined profiles don't have a mode string appended */ if (!unconfined(profile)) mode_len = strlen(mode_str) + 3; /* + 3 for _() */ name_len = strlen(profile->base.hname); len = mode_len + ns_len + name_len + 1; /* + 1 for \n */ s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */ if (!str) return -ENOMEM; if (ns_len) { /* skip over prefix current_ns->base.hname and separating // */ sprintf(s, ":%s://", ns_name); s += ns_len; } if (unconfined(profile)) /* mode string not being appended */ sprintf(s, "%s\n", profile->base.hname); else sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); *string = str; /* NOTE: len does not include \0 of string, not saved as part of file */ return len; } /** * split_token_from_name - separate a string of form ^ * @op: operation being checked * @args: string to parse (NOT NULL) * @token: stores returned parsed token value (NOT NULL) * * Returns: start position of name after token else NULL on failure */ static char *split_token_from_name(int op, char *args, u64 * token) { char *name; *token = simple_strtoull(args, &name, 16); if ((name == args) || *name != '^') { AA_ERROR("%s: Invalid input '%s'", op_table[op], args); return ERR_PTR(-EINVAL); } name++; /* skip ^ */ if (!*name) name = NULL; return name; } /** * aa_setprocattr_chagnehat - handle procattr interface to change_hat * @args: args received from writing to /proc//attr/current (NOT NULL) * @size: size of the args * @test: true if this is a test of change_hat permissions * * Returns: %0 or error code if change_hat fails */ int aa_setprocattr_changehat(char *args, size_t size, int test) { char *hat; u64 token; const char *hats[16]; /* current hard limit on # of names */ int count = 0; hat = split_token_from_name(OP_CHANGE_HAT, args, &token); if (IS_ERR(hat)) return PTR_ERR(hat); if (!hat && !token) { AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic"); return -EINVAL; } if (hat) { /* set up hat name vector, args guaranteed null terminated * at args[size] by setprocattr. * * If there are multiple hat names in the buffer each is * separated by a \0. Ie. userspace writes them pre tokenized */ char *end = args + size; for (count = 0; (hat < end) && count < 16; ++count) { char *next = hat + strlen(hat) + 1; hats[count] = hat; hat = next; } } AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n", __func__, token, hat ? hat : NULL); return aa_change_hat(hats, count, token, test); } /** * aa_setprocattr_changeprofile - handle procattr interface to changeprofile * @fqname: args received from writting to /proc//attr/current (NOT NULL) * @onexec: true if change_profile should be delayed until exec * @test: true if this is a test of change_profile permissions * * Returns: %0 or error code if change_profile fails */ int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test) { char *name, *ns_name; name = aa_split_fqname(fqname, &ns_name); return aa_change_profile(ns_name, name, onexec, test); } ry='commit info' class='commit-info'> authorPeter Zijlstra <peterz@infradead.org>2017-01-26 16:39:55 +0100 committerIngo Molnar <mingo@kernel.org>2017-01-30 11:41:25 +0100 commita76a82a3e38c8d3fb6499e3dfaeb0949241ab588 (patch) treeb5bc906278fe1ac66d75de984d26bf59b43b3ed8 /security/selinux/ss/services.c parent566cf877a1fcb6d6dc0126b076aad062054c2637 (diff)
perf/core: Fix use-after-free bug
Dmitry reported a KASAN use-after-free on event->group_leader. It turns out there's a hole in perf_remove_from_context() due to event_function_call() not calling its function when the task associated with the event is already dead. In this case the event will have been detached from the task, but the grouping will have been retained, such that group operations might still work properly while there are live child events etc. This does however mean that we can miss a perf_group_detach() call when the group decomposes, this in turn can then lead to use-after-free. Fix it by explicitly doing the group detach if its still required. Reported-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org # v4.5+ Cc: syzkaller <syzkaller@googlegroups.com> Fixes: 63b6da39bb38 ("perf: Fix perf_event_exit_task() race") Link: http://lkml.kernel.org/r/20170126153955.GD6515@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'security/selinux/ss/services.c')