mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 12:33:18 -04:00
Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: - Extend LSM stacking to allow sharing of cred, file, ipc, inode, and task blobs. This paves the way for more full-featured LSMs to be merged, and is specifically aimed at LandLock and SARA LSMs. This work is from Casey and Kees. - There's a new LSM from Micah Morton: "SafeSetID gates the setid family of syscalls to restrict UID/GID transitions from a given UID/GID to only those approved by a system-wide whitelist." This feature is currently shipping in ChromeOS. * 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (62 commits) keys: fix missing __user in KEYCTL_PKEY_QUERY LSM: Update list of SECURITYFS users in Kconfig LSM: Ignore "security=" when "lsm=" is specified LSM: Update function documentation for cap_capable security: mark expected switch fall-throughs and add a missing break tomoyo: Bump version. LSM: fix return value check in safesetid_init_securityfs() LSM: SafeSetID: add selftest LSM: SafeSetID: remove unused include LSM: SafeSetID: 'depend' on CONFIG_SECURITY LSM: Add 'name' field for SafeSetID in DEFINE_LSM LSM: add SafeSetID module that gates setid calls LSM: add SafeSetID module that gates setid calls tomoyo: Allow multiple use_group lines. tomoyo: Coding style fix. tomoyo: Swicth from cred->security to task_struct->security. security: keys: annotate implicit fall throughs security: keys: annotate implicit fall throughs security: keys: annotate implicit fall through capabilities:: annotate implicit fall through ...
This commit is contained in:
@@ -93,9 +93,7 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
|
||||
break;
|
||||
case _LINUX_CAPABILITY_VERSION_2:
|
||||
warn_deprecated_v2();
|
||||
/*
|
||||
* fall through - v3 is otherwise equivalent to v2.
|
||||
*/
|
||||
/* fall through - v3 is otherwise equivalent to v2. */
|
||||
case _LINUX_CAPABILITY_VERSION_3:
|
||||
*tocopy = _LINUX_CAPABILITY_U32S_3;
|
||||
break;
|
||||
@@ -299,7 +297,7 @@ bool has_ns_capability(struct task_struct *t,
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = security_capable(__task_cred(t), ns, cap);
|
||||
ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE);
|
||||
rcu_read_unlock();
|
||||
|
||||
return (ret == 0);
|
||||
@@ -340,7 +338,7 @@ bool has_ns_capability_noaudit(struct task_struct *t,
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = security_capable_noaudit(__task_cred(t), ns, cap);
|
||||
ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT);
|
||||
rcu_read_unlock();
|
||||
|
||||
return (ret == 0);
|
||||
@@ -363,7 +361,9 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
|
||||
return has_ns_capability_noaudit(t, &init_user_ns, cap);
|
||||
}
|
||||
|
||||
static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
|
||||
static bool ns_capable_common(struct user_namespace *ns,
|
||||
int cap,
|
||||
unsigned int opts)
|
||||
{
|
||||
int capable;
|
||||
|
||||
@@ -372,8 +372,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
|
||||
BUG();
|
||||
}
|
||||
|
||||
capable = audit ? security_capable(current_cred(), ns, cap) :
|
||||
security_capable_noaudit(current_cred(), ns, cap);
|
||||
capable = security_capable(current_cred(), ns, cap, opts);
|
||||
if (capable == 0) {
|
||||
current->flags |= PF_SUPERPRIV;
|
||||
return true;
|
||||
@@ -394,7 +393,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
|
||||
*/
|
||||
bool ns_capable(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return ns_capable_common(ns, cap, true);
|
||||
return ns_capable_common(ns, cap, CAP_OPT_NONE);
|
||||
}
|
||||
EXPORT_SYMBOL(ns_capable);
|
||||
|
||||
@@ -412,10 +411,29 @@ EXPORT_SYMBOL(ns_capable);
|
||||
*/
|
||||
bool ns_capable_noaudit(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return ns_capable_common(ns, cap, false);
|
||||
return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT);
|
||||
}
|
||||
EXPORT_SYMBOL(ns_capable_noaudit);
|
||||
|
||||
/**
|
||||
* ns_capable_setid - Determine if the current task has a superior capability
|
||||
* in effect, while signalling that this check is being done from within a
|
||||
* setid syscall.
|
||||
* @ns: The usernamespace we want the capability in
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
* Return true if the current task has the given superior capability currently
|
||||
* available for use, false if not.
|
||||
*
|
||||
* This sets PF_SUPERPRIV on the task if the capability is available on the
|
||||
* assumption that it's about to be used.
|
||||
*/
|
||||
bool ns_capable_setid(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return ns_capable_common(ns, cap, CAP_OPT_INSETID);
|
||||
}
|
||||
EXPORT_SYMBOL(ns_capable_setid);
|
||||
|
||||
/**
|
||||
* capable - Determine if the current task has a superior capability in effect
|
||||
* @cap: The capability to be tested for
|
||||
@@ -448,10 +466,11 @@ EXPORT_SYMBOL(capable);
|
||||
bool file_ns_capable(const struct file *file, struct user_namespace *ns,
|
||||
int cap)
|
||||
{
|
||||
|
||||
if (WARN_ON_ONCE(!cap_valid(cap)))
|
||||
return false;
|
||||
|
||||
if (security_capable(file->f_cred, ns, cap) == 0)
|
||||
if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -500,10 +519,12 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
|
||||
{
|
||||
int ret = 0; /* An absent tracer adds no restrictions */
|
||||
const struct cred *cred;
|
||||
|
||||
rcu_read_lock();
|
||||
cred = rcu_dereference(tsk->ptracer_cred);
|
||||
if (cred)
|
||||
ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE);
|
||||
ret = security_capable(cred, ns, CAP_SYS_PTRACE,
|
||||
CAP_OPT_NOAUDIT);
|
||||
rcu_read_unlock();
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
@@ -760,19 +760,6 @@ bool creds_are_invalid(const struct cred *cred)
|
||||
{
|
||||
if (cred->magic != CRED_MAGIC)
|
||||
return true;
|
||||
#ifdef CONFIG_SECURITY_SELINUX
|
||||
/*
|
||||
* cred->security == NULL if security_cred_alloc_blank() or
|
||||
* security_prepare_creds() returned an error.
|
||||
*/
|
||||
if (selinux_is_enabled() && cred->security) {
|
||||
if ((unsigned long) cred->security < PAGE_SIZE)
|
||||
return true;
|
||||
if ((*(u32 *)cred->security & 0xffffff00) ==
|
||||
(POISON_FREE << 24 | POISON_FREE << 16 | POISON_FREE << 8))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(creds_are_invalid);
|
||||
|
||||
@@ -445,8 +445,8 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
|
||||
* behavior of privileged children.
|
||||
*/
|
||||
if (!task_no_new_privs(current) &&
|
||||
security_capable_noaudit(current_cred(), current_user_ns(),
|
||||
CAP_SYS_ADMIN) != 0)
|
||||
security_capable(current_cred(), current_user_ns(),
|
||||
CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0)
|
||||
return ERR_PTR(-EACCES);
|
||||
|
||||
/* Allocate a new seccomp_filter */
|
||||
|
||||
10
kernel/sys.c
10
kernel/sys.c
@@ -516,7 +516,7 @@ long __sys_setreuid(uid_t ruid, uid_t euid)
|
||||
new->uid = kruid;
|
||||
if (!uid_eq(old->uid, kruid) &&
|
||||
!uid_eq(old->euid, kruid) &&
|
||||
!ns_capable(old->user_ns, CAP_SETUID))
|
||||
!ns_capable_setid(old->user_ns, CAP_SETUID))
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ long __sys_setreuid(uid_t ruid, uid_t euid)
|
||||
if (!uid_eq(old->uid, keuid) &&
|
||||
!uid_eq(old->euid, keuid) &&
|
||||
!uid_eq(old->suid, keuid) &&
|
||||
!ns_capable(old->user_ns, CAP_SETUID))
|
||||
!ns_capable_setid(old->user_ns, CAP_SETUID))
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ long __sys_setuid(uid_t uid)
|
||||
old = current_cred();
|
||||
|
||||
retval = -EPERM;
|
||||
if (ns_capable(old->user_ns, CAP_SETUID)) {
|
||||
if (ns_capable_setid(old->user_ns, CAP_SETUID)) {
|
||||
new->suid = new->uid = kuid;
|
||||
if (!uid_eq(kuid, old->uid)) {
|
||||
retval = set_user(new);
|
||||
@@ -646,7 +646,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
||||
old = current_cred();
|
||||
|
||||
retval = -EPERM;
|
||||
if (!ns_capable(old->user_ns, CAP_SETUID)) {
|
||||
if (!ns_capable_setid(old->user_ns, CAP_SETUID)) {
|
||||
if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
|
||||
!uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
|
||||
goto error;
|
||||
@@ -814,7 +814,7 @@ long __sys_setfsuid(uid_t uid)
|
||||
|
||||
if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) ||
|
||||
uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
|
||||
ns_capable(old->user_ns, CAP_SETUID)) {
|
||||
ns_capable_setid(old->user_ns, CAP_SETUID)) {
|
||||
if (!uid_eq(kuid, old->fsuid)) {
|
||||
new->fsuid = kuid;
|
||||
if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
|
||||
|
||||
Reference in New Issue
Block a user