mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07: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:
@@ -0,0 +1,107 @@
|
||||
=========
|
||||
SafeSetID
|
||||
=========
|
||||
SafeSetID is an LSM module that 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. These restrictions also prohibit the given UIDs/GIDs
|
||||
from obtaining auxiliary privileges associated with CAP_SET{U/G}ID, such as
|
||||
allowing a user to set up user namespace UID mappings.
|
||||
|
||||
|
||||
Background
|
||||
==========
|
||||
In absence of file capabilities, processes spawned on a Linux system that need
|
||||
to switch to a different user must be spawned with CAP_SETUID privileges.
|
||||
CAP_SETUID is granted to programs running as root or those running as a non-root
|
||||
user that have been explicitly given the CAP_SETUID runtime capability. It is
|
||||
often preferable to use Linux runtime capabilities rather than file
|
||||
capabilities, since using file capabilities to run a program with elevated
|
||||
privileges opens up possible security holes since any user with access to the
|
||||
file can exec() that program to gain the elevated privileges.
|
||||
|
||||
While it is possible to implement a tree of processes by giving full
|
||||
CAP_SET{U/G}ID capabilities, this is often at odds with the goals of running a
|
||||
tree of processes under non-root user(s) in the first place. Specifically,
|
||||
since CAP_SETUID allows changing to any user on the system, including the root
|
||||
user, it is an overpowered capability for what is needed in this scenario,
|
||||
especially since programs often only call setuid() to drop privileges to a
|
||||
lesser-privileged user -- not elevate privileges. Unfortunately, there is no
|
||||
generally feasible way in Linux to restrict the potential UIDs that a user can
|
||||
switch to through setuid() beyond allowing a switch to any user on the system.
|
||||
This SafeSetID LSM seeks to provide a solution for restricting setid
|
||||
capabilities in such a way.
|
||||
|
||||
The main use case for this LSM is to allow a non-root program to transition to
|
||||
other untrusted uids without full blown CAP_SETUID capabilities. The non-root
|
||||
program would still need CAP_SETUID to do any kind of transition, but the
|
||||
additional restrictions imposed by this LSM would mean it is a "safer" version
|
||||
of CAP_SETUID since the non-root program cannot take advantage of CAP_SETUID to
|
||||
do any unapproved actions (e.g. setuid to uid 0 or create/enter new user
|
||||
namespace). The higher level goal is to allow for uid-based sandboxing of system
|
||||
services without having to give out CAP_SETUID all over the place just so that
|
||||
non-root programs can drop to even-lesser-privileged uids. This is especially
|
||||
relevant when one non-root daemon on the system should be allowed to spawn other
|
||||
processes as different uids, but its undesirable to give the daemon a
|
||||
basically-root-equivalent CAP_SETUID.
|
||||
|
||||
|
||||
Other Approaches Considered
|
||||
===========================
|
||||
|
||||
Solve this problem in userspace
|
||||
-------------------------------
|
||||
For candidate applications that would like to have restricted setid capabilities
|
||||
as implemented in this LSM, an alternative option would be to simply take away
|
||||
setid capabilities from the application completely and refactor the process
|
||||
spawning semantics in the application (e.g. by using a privileged helper program
|
||||
to do process spawning and UID/GID transitions). Unfortunately, there are a
|
||||
number of semantics around process spawning that would be affected by this, such
|
||||
as fork() calls where the program doesn???t immediately call exec() after the
|
||||
fork(), parent processes specifying custom environment variables or command line
|
||||
args for spawned child processes, or inheritance of file handles across a
|
||||
fork()/exec(). Because of this, as solution that uses a privileged helper in
|
||||
userspace would likely be less appealing to incorporate into existing projects
|
||||
that rely on certain process-spawning semantics in Linux.
|
||||
|
||||
Use user namespaces
|
||||
-------------------
|
||||
Another possible approach would be to run a given process tree in its own user
|
||||
namespace and give programs in the tree setid capabilities. In this way,
|
||||
programs in the tree could change to any desired UID/GID in the context of their
|
||||
own user namespace, and only approved UIDs/GIDs could be mapped back to the
|
||||
initial system user namespace, affectively preventing privilege escalation.
|
||||
Unfortunately, it is not generally feasible to use user namespaces in isolation,
|
||||
without pairing them with other namespace types, which is not always an option.
|
||||
Linux checks for capabilities based off of the user namespace that ???owns??? some
|
||||
entity. For example, Linux has the notion that network namespaces are owned by
|
||||
the user namespace in which they were created. A consequence of this is that
|
||||
capability checks for access to a given network namespace are done by checking
|
||||
whether a task has the given capability in the context of the user namespace
|
||||
that owns the network namespace -- not necessarily the user namespace under
|
||||
which the given task runs. Therefore spawning a process in a new user namespace
|
||||
effectively prevents it from accessing the network namespace owned by the
|
||||
initial namespace. This is a deal-breaker for any application that expects to
|
||||
retain the CAP_NET_ADMIN capability for the purpose of adjusting network
|
||||
configurations. Using user namespaces in isolation causes problems regarding
|
||||
other system interactions, including use of pid namespaces and device creation.
|
||||
|
||||
Use an existing LSM
|
||||
-------------------
|
||||
None of the other in-tree LSMs have the capability to gate setid transitions, or
|
||||
even employ the security_task_fix_setuid hook at all. SELinux says of that hook:
|
||||
"Since setuid only affects the current process, and since the SELinux controls
|
||||
are not based on the Linux identity attributes, SELinux does not need to control
|
||||
this operation."
|
||||
|
||||
|
||||
Directions for use
|
||||
==================
|
||||
This LSM hooks the setid syscalls to make sure transitions are allowed if an
|
||||
applicable restriction policy is in place. Policies are configured through
|
||||
securityfs by writing to the safesetid/add_whitelist_policy and
|
||||
safesetid/flush_whitelist_policies files at the location where securityfs is
|
||||
mounted. The format for adding a policy is '<UID>:<UID>', using literal
|
||||
numbers, such as '123:456'. To flush the policies, any write to the file is
|
||||
sufficient. Again, configuring a policy for a UID will prevent that UID from
|
||||
obtaining auxiliary setid privileges, such as allowing a user to set up user
|
||||
namespace UID mappings.
|
||||
@@ -17,9 +17,8 @@ MAC extensions, other extensions can be built using the LSM to provide
|
||||
specific changes to system operation when these tweaks are not available
|
||||
in the core functionality of Linux itself.
|
||||
|
||||
Without a specific LSM built into the kernel, the default LSM will be the
|
||||
Linux capabilities system. Most LSMs choose to extend the capabilities
|
||||
system, building their checks on top of the defined capability hooks.
|
||||
The Linux capabilities modules will always be included. This may be
|
||||
followed by any number of "minor" modules and at most one "major" module.
|
||||
For more details on capabilities, see ``capabilities(7)`` in the Linux
|
||||
man-pages project.
|
||||
|
||||
@@ -30,6 +29,14 @@ order in which checks are made. The capability module will always
|
||||
be first, followed by any "minor" modules (e.g. Yama) and then
|
||||
the one "major" module (e.g. SELinux) if there is one configured.
|
||||
|
||||
Process attributes associated with "major" security modules should
|
||||
be accessed and maintained using the special files in ``/proc/.../attr``.
|
||||
A security module may maintain a module specific subdirectory there,
|
||||
named after the module. ``/proc/.../attr/smack`` is provided by the Smack
|
||||
security module and contains all its special files. The files directly
|
||||
in ``/proc/.../attr`` remain as legacy interfaces for modules that provide
|
||||
subdirectories.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
@@ -39,3 +46,4 @@ the one "major" module (e.g. SELinux) if there is one configured.
|
||||
Smack
|
||||
tomoyo
|
||||
Yama
|
||||
SafeSetID
|
||||
|
||||
@@ -2333,6 +2333,10 @@
|
||||
|
||||
lsm.debug [SECURITY] Enable LSM initialization debugging output.
|
||||
|
||||
lsm=lsm1,...,lsmN
|
||||
[SECURITY] Choose order of LSM initialization. This
|
||||
overrides CONFIG_LSM, and the "security=" parameter.
|
||||
|
||||
machvec= [IA-64] Force the use of a particular machine-vector
|
||||
(machvec) in a generic kernel.
|
||||
Example: machvec=hpzx1_swiotlb
|
||||
@@ -4110,11 +4114,9 @@
|
||||
Note: increases power consumption, thus should only be
|
||||
enabled if running jitter sensitive (HPC/RT) workloads.
|
||||
|
||||
security= [SECURITY] Choose a security module to enable at boot.
|
||||
If this boot parameter is not specified, only the first
|
||||
security module asking for security registration will be
|
||||
loaded. An invalid security module name will be treated
|
||||
as if no module has been chosen.
|
||||
security= [SECURITY] Choose a legacy "major" security module to
|
||||
enable at boot. This has been deprecated by the
|
||||
"lsm=" parameter.
|
||||
|
||||
selinux= [SELINUX] Disable or enable SELinux at boot time.
|
||||
Format: { "0" | "1" }
|
||||
|
||||
+5
-6
@@ -15557,12 +15557,11 @@ F: mm/shmem.c
|
||||
TOMOYO SECURITY MODULE
|
||||
M: Kentaro Takeda <takedakn@nttdata.co.jp>
|
||||
M: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
|
||||
L: tomoyo-dev-en@lists.sourceforge.jp (subscribers-only, for developers in English)
|
||||
L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
|
||||
L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
|
||||
L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
|
||||
W: http://tomoyo.sourceforge.jp/
|
||||
T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.5.x/tomoyo-lsm/patches/
|
||||
L: tomoyo-dev-en@lists.osdn.me (subscribers-only, for developers in English)
|
||||
L: tomoyo-users-en@lists.osdn.me (subscribers-only, for users in English)
|
||||
L: tomoyo-dev@lists.osdn.me (subscribers-only, for developers in Japanese)
|
||||
L: tomoyo-users@lists.osdn.me (subscribers-only, for users in Japanese)
|
||||
W: https://tomoyo.osdn.jp/
|
||||
S: Maintained
|
||||
F: security/tomoyo/
|
||||
|
||||
|
||||
+55
-9
@@ -140,9 +140,13 @@ struct pid_entry {
|
||||
#define REG(NAME, MODE, fops) \
|
||||
NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
|
||||
#define ONE(NAME, MODE, show) \
|
||||
NOD(NAME, (S_IFREG|(MODE)), \
|
||||
NOD(NAME, (S_IFREG|(MODE)), \
|
||||
NULL, &proc_single_file_operations, \
|
||||
{ .proc_show = show } )
|
||||
#define ATTR(LSM, NAME, MODE) \
|
||||
NOD(NAME, (S_IFREG|(MODE)), \
|
||||
NULL, &proc_pid_attr_operations, \
|
||||
{ .lsm = LSM })
|
||||
|
||||
/*
|
||||
* Count the number of hardlinks for the pid_entry table, excluding the .
|
||||
@@ -2521,7 +2525,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
|
||||
if (!task)
|
||||
return -ESRCH;
|
||||
|
||||
length = security_getprocattr(task,
|
||||
length = security_getprocattr(task, PROC_I(inode)->op.lsm,
|
||||
(char*)file->f_path.dentry->d_name.name,
|
||||
&p);
|
||||
put_task_struct(task);
|
||||
@@ -2570,7 +2574,9 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
|
||||
if (rv < 0)
|
||||
goto out_free;
|
||||
|
||||
rv = security_setprocattr(file->f_path.dentry->d_name.name, page, count);
|
||||
rv = security_setprocattr(PROC_I(inode)->op.lsm,
|
||||
file->f_path.dentry->d_name.name, page,
|
||||
count);
|
||||
mutex_unlock(¤t->signal->cred_guard_mutex);
|
||||
out_free:
|
||||
kfree(page);
|
||||
@@ -2584,13 +2590,53 @@ static const struct file_operations proc_pid_attr_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
#define LSM_DIR_OPS(LSM) \
|
||||
static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
|
||||
struct dir_context *ctx) \
|
||||
{ \
|
||||
return proc_pident_readdir(filp, ctx, \
|
||||
LSM##_attr_dir_stuff, \
|
||||
ARRAY_SIZE(LSM##_attr_dir_stuff)); \
|
||||
} \
|
||||
\
|
||||
static const struct file_operations proc_##LSM##_attr_dir_ops = { \
|
||||
.read = generic_read_dir, \
|
||||
.iterate = proc_##LSM##_attr_dir_iterate, \
|
||||
.llseek = default_llseek, \
|
||||
}; \
|
||||
\
|
||||
static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
|
||||
struct dentry *dentry, unsigned int flags) \
|
||||
{ \
|
||||
return proc_pident_lookup(dir, dentry, \
|
||||
LSM##_attr_dir_stuff, \
|
||||
ARRAY_SIZE(LSM##_attr_dir_stuff)); \
|
||||
} \
|
||||
\
|
||||
static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
|
||||
.lookup = proc_##LSM##_attr_dir_lookup, \
|
||||
.getattr = pid_getattr, \
|
||||
.setattr = proc_setattr, \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK
|
||||
static const struct pid_entry smack_attr_dir_stuff[] = {
|
||||
ATTR("smack", "current", 0666),
|
||||
};
|
||||
LSM_DIR_OPS(smack);
|
||||
#endif
|
||||
|
||||
static const struct pid_entry attr_dir_stuff[] = {
|
||||
REG("current", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
|
||||
REG("prev", S_IRUGO, proc_pid_attr_operations),
|
||||
REG("exec", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
|
||||
REG("fscreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
|
||||
REG("keycreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
|
||||
REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
|
||||
ATTR(NULL, "current", 0666),
|
||||
ATTR(NULL, "prev", 0444),
|
||||
ATTR(NULL, "exec", 0666),
|
||||
ATTR(NULL, "fscreate", 0666),
|
||||
ATTR(NULL, "keycreate", 0666),
|
||||
ATTR(NULL, "sockcreate", 0666),
|
||||
#ifdef CONFIG_SECURITY_SMACK
|
||||
DIR("smack", 0555,
|
||||
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
|
||||
#endif
|
||||
};
|
||||
|
||||
static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx)
|
||||
|
||||
@@ -82,6 +82,7 @@ union proc_op {
|
||||
int (*proc_show)(struct seq_file *m,
|
||||
struct pid_namespace *ns, struct pid *pid,
|
||||
struct task_struct *task);
|
||||
const char *lsm;
|
||||
};
|
||||
|
||||
struct proc_inode {
|
||||
|
||||
@@ -209,6 +209,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
|
||||
extern bool capable(int cap);
|
||||
extern bool ns_capable(struct user_namespace *ns, int cap);
|
||||
extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
|
||||
extern bool ns_capable_setid(struct user_namespace *ns, int cap);
|
||||
#else
|
||||
static inline bool has_capability(struct task_struct *t, int cap)
|
||||
{
|
||||
@@ -240,6 +241,10 @@ static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static inline bool ns_capable_setid(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_MULTIUSER */
|
||||
extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
|
||||
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/capability.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/key.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/uidgid.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
+30
-15
@@ -1270,7 +1270,7 @@
|
||||
* @cred contains the credentials to use.
|
||||
* @ns contains the user namespace we want the capability in
|
||||
* @cap contains the capability <include/linux/capability.h>.
|
||||
* @audit contains whether to write an audit message or not
|
||||
* @opts contains options for the capable check <include/linux/security.h>
|
||||
* Return 0 if the capability is granted for @tsk.
|
||||
* @syslog:
|
||||
* Check permission before accessing the kernel message ring or changing
|
||||
@@ -1446,8 +1446,10 @@ union security_list_options {
|
||||
const kernel_cap_t *effective,
|
||||
const kernel_cap_t *inheritable,
|
||||
const kernel_cap_t *permitted);
|
||||
int (*capable)(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit);
|
||||
int (*capable)(const struct cred *cred,
|
||||
struct user_namespace *ns,
|
||||
int cap,
|
||||
unsigned int opts);
|
||||
int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
|
||||
int (*quota_on)(struct dentry *dentry);
|
||||
int (*syslog)(int type);
|
||||
@@ -2027,6 +2029,18 @@ struct security_hook_list {
|
||||
char *lsm;
|
||||
} __randomize_layout;
|
||||
|
||||
/*
|
||||
* Security blob size or offset data.
|
||||
*/
|
||||
struct lsm_blob_sizes {
|
||||
int lbs_cred;
|
||||
int lbs_file;
|
||||
int lbs_inode;
|
||||
int lbs_ipc;
|
||||
int lbs_msg_msg;
|
||||
int lbs_task;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initializing a security_hook_list structure takes
|
||||
* up a lot of space in a source file. This macro takes
|
||||
@@ -2042,9 +2056,21 @@ extern char *lsm_names;
|
||||
extern void security_add_hooks(struct security_hook_list *hooks, int count,
|
||||
char *lsm);
|
||||
|
||||
#define LSM_FLAG_LEGACY_MAJOR BIT(0)
|
||||
#define LSM_FLAG_EXCLUSIVE BIT(1)
|
||||
|
||||
enum lsm_order {
|
||||
LSM_ORDER_FIRST = -1, /* This is only for capabilities. */
|
||||
LSM_ORDER_MUTABLE = 0,
|
||||
};
|
||||
|
||||
struct lsm_info {
|
||||
const char *name; /* Required. */
|
||||
enum lsm_order order; /* Optional: default is LSM_ORDER_MUTABLE */
|
||||
unsigned long flags; /* Optional: flags describing LSM */
|
||||
int *enabled; /* Optional: controlled by CONFIG_LSM */
|
||||
int (*init)(void); /* Required. */
|
||||
struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
|
||||
};
|
||||
|
||||
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
|
||||
@@ -2084,17 +2110,6 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
|
||||
#define __lsm_ro_after_init __ro_after_init
|
||||
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
|
||||
|
||||
extern int __init security_module_enable(const char *module);
|
||||
extern void __init capability_add_hooks(void);
|
||||
#ifdef CONFIG_SECURITY_YAMA
|
||||
extern void __init yama_add_hooks(void);
|
||||
#else
|
||||
static inline void __init yama_add_hooks(void) { }
|
||||
#endif
|
||||
#ifdef CONFIG_SECURITY_LOADPIN
|
||||
void __init loadpin_add_hooks(void);
|
||||
#else
|
||||
static inline void loadpin_add_hooks(void) { };
|
||||
#endif
|
||||
extern int lsm_inode_alloc(struct inode *inode);
|
||||
|
||||
#endif /* ! __LINUX_LSM_HOOKS_H */
|
||||
|
||||
+24
-19
@@ -54,9 +54,12 @@ struct xattr;
|
||||
struct xfrm_sec_ctx;
|
||||
struct mm_struct;
|
||||
|
||||
/* Default (no) options for the capable function */
|
||||
#define CAP_OPT_NONE 0x0
|
||||
/* If capable should audit the security request */
|
||||
#define SECURITY_CAP_NOAUDIT 0
|
||||
#define SECURITY_CAP_AUDIT 1
|
||||
#define CAP_OPT_NOAUDIT BIT(1)
|
||||
/* If capable is being called by a setid function */
|
||||
#define CAP_OPT_INSETID BIT(2)
|
||||
|
||||
/* LSM Agnostic defines for sb_set_mnt_opts */
|
||||
#define SECURITY_LSM_NATIVE_LABELS 1
|
||||
@@ -72,7 +75,7 @@ enum lsm_event {
|
||||
|
||||
/* These functions are in security/commoncap.c */
|
||||
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit);
|
||||
int cap, unsigned int opts);
|
||||
extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
|
||||
extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
|
||||
extern int cap_ptrace_traceme(struct task_struct *parent);
|
||||
@@ -207,10 +210,10 @@ int security_capset(struct cred *new, const struct cred *old,
|
||||
const kernel_cap_t *effective,
|
||||
const kernel_cap_t *inheritable,
|
||||
const kernel_cap_t *permitted);
|
||||
int security_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap);
|
||||
int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap);
|
||||
int security_capable(const struct cred *cred,
|
||||
struct user_namespace *ns,
|
||||
int cap,
|
||||
unsigned int opts);
|
||||
int security_quotactl(int cmds, int type, int id, struct super_block *sb);
|
||||
int security_quota_on(struct dentry *dentry);
|
||||
int security_syslog(int type);
|
||||
@@ -366,8 +369,10 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd);
|
||||
int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
|
||||
unsigned nsops, int alter);
|
||||
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
|
||||
int security_getprocattr(struct task_struct *p, char *name, char **value);
|
||||
int security_setprocattr(const char *name, void *value, size_t size);
|
||||
int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
|
||||
char **value);
|
||||
int security_setprocattr(const char *lsm, const char *name, void *value,
|
||||
size_t size);
|
||||
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
|
||||
int security_ismaclabel(const char *name);
|
||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
@@ -462,14 +467,11 @@ static inline int security_capset(struct cred *new,
|
||||
}
|
||||
|
||||
static inline int security_capable(const struct cred *cred,
|
||||
struct user_namespace *ns, int cap)
|
||||
struct user_namespace *ns,
|
||||
int cap,
|
||||
unsigned int opts)
|
||||
{
|
||||
return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT);
|
||||
}
|
||||
|
||||
static inline int security_capable_noaudit(const struct cred *cred,
|
||||
struct user_namespace *ns, int cap) {
|
||||
return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
|
||||
return cap_capable(cred, ns, cap, opts);
|
||||
}
|
||||
|
||||
static inline int security_quotactl(int cmds, int type, int id,
|
||||
@@ -1112,15 +1114,18 @@ static inline int security_sem_semop(struct kern_ipc_perm *sma,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode)
|
||||
static inline void security_d_instantiate(struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{ }
|
||||
|
||||
static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
|
||||
static inline int security_getprocattr(struct task_struct *p, const char *lsm,
|
||||
char *name, char **value)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int security_setprocattr(char *name, void *value, size_t size)
|
||||
static inline int security_setprocattr(const char *lsm, char *name,
|
||||
void *value, size_t size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* SELinux services exported to the rest of the kernel.
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
* Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
|
||||
* Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef _LINUX_SELINUX_H
|
||||
#define _LINUX_SELINUX_H
|
||||
|
||||
struct selinux_audit_rule;
|
||||
struct audit_context;
|
||||
struct kern_ipc_perm;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX
|
||||
|
||||
/**
|
||||
* selinux_is_enabled - is SELinux enabled?
|
||||
*/
|
||||
bool selinux_is_enabled(void);
|
||||
#else
|
||||
|
||||
static inline bool selinux_is_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_SECURITY_SELINUX */
|
||||
|
||||
#endif /* _LINUX_SELINUX_H */
|
||||
+33
-12
@@ -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);
|
||||
|
||||
+2
-2
@@ -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 */
|
||||
|
||||
+5
-5
@@ -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)
|
||||
|
||||
+9
-36
@@ -40,8 +40,7 @@ config SECURITYFS
|
||||
bool "Enable the securityfs filesystem"
|
||||
help
|
||||
This will build the securityfs filesystem. It is currently used by
|
||||
the TPM bios character driver and IMA, an integrity provider. It is
|
||||
not used by SELinux or SMACK.
|
||||
various security modules (AppArmor, IMA, SafeSetID, TOMOYO, TPM).
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
@@ -236,45 +235,19 @@ source "security/tomoyo/Kconfig"
|
||||
source "security/apparmor/Kconfig"
|
||||
source "security/loadpin/Kconfig"
|
||||
source "security/yama/Kconfig"
|
||||
source "security/safesetid/Kconfig"
|
||||
|
||||
source "security/integrity/Kconfig"
|
||||
|
||||
choice
|
||||
prompt "Default security module"
|
||||
default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
|
||||
default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
|
||||
default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
|
||||
default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
|
||||
default DEFAULT_SECURITY_DAC
|
||||
|
||||
config LSM
|
||||
string "Ordered list of enabled LSMs"
|
||||
default "yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
|
||||
help
|
||||
Select the security module that will be used by default if the
|
||||
kernel parameter security= is not specified.
|
||||
A comma-separated list of LSMs, in initialization order.
|
||||
Any LSMs left off this list will be ignored. This can be
|
||||
controlled at boot with the "lsm=" parameter.
|
||||
|
||||
config DEFAULT_SECURITY_SELINUX
|
||||
bool "SELinux" if SECURITY_SELINUX=y
|
||||
|
||||
config DEFAULT_SECURITY_SMACK
|
||||
bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y
|
||||
|
||||
config DEFAULT_SECURITY_TOMOYO
|
||||
bool "TOMOYO" if SECURITY_TOMOYO=y
|
||||
|
||||
config DEFAULT_SECURITY_APPARMOR
|
||||
bool "AppArmor" if SECURITY_APPARMOR=y
|
||||
|
||||
config DEFAULT_SECURITY_DAC
|
||||
bool "Unix Discretionary Access Controls"
|
||||
|
||||
endchoice
|
||||
|
||||
config DEFAULT_SECURITY
|
||||
string
|
||||
default "selinux" if DEFAULT_SECURITY_SELINUX
|
||||
default "smack" if DEFAULT_SECURITY_SMACK
|
||||
default "tomoyo" if DEFAULT_SECURITY_TOMOYO
|
||||
default "apparmor" if DEFAULT_SECURITY_APPARMOR
|
||||
default "" if DEFAULT_SECURITY_DAC
|
||||
If unsure, leave this as the default.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
|
||||
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
|
||||
subdir-$(CONFIG_SECURITY_YAMA) += yama
|
||||
subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin
|
||||
subdir-$(CONFIG_SECURITY_SAFESETID) += safesetid
|
||||
|
||||
# always enable default capabilities
|
||||
obj-y += commoncap.o
|
||||
@@ -25,6 +26,7 @@ obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
|
||||
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
|
||||
obj-$(CONFIG_SECURITY_YAMA) += yama/
|
||||
obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/
|
||||
obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/
|
||||
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
|
||||
|
||||
# Object integrity file lists
|
||||
|
||||
@@ -14,22 +14,6 @@ config SECURITY_APPARMOR
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_APPARMOR_BOOTPARAM_VALUE
|
||||
int "AppArmor boot parameter default value"
|
||||
depends on SECURITY_APPARMOR
|
||||
range 0 1
|
||||
default 1
|
||||
help
|
||||
This option sets the default value for the kernel parameter
|
||||
'apparmor', which allows AppArmor to be enabled or disabled
|
||||
at boot. If this option is set to 0 (zero), the AppArmor
|
||||
kernel parameter will default to 0, disabling AppArmor at
|
||||
boot. If this option is set to 1 (one), the AppArmor
|
||||
kernel parameter will default to 1, enabling AppArmor at
|
||||
boot.
|
||||
|
||||
If you are unsure how to answer this question, answer 1.
|
||||
|
||||
config SECURITY_APPARMOR_HASH
|
||||
bool "Enable introspection of sha1 hashes for loaded profiles"
|
||||
depends on SECURITY_APPARMOR
|
||||
|
||||
@@ -110,13 +110,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
|
||||
* profile_capable - test if profile allows use of capability @cap
|
||||
* @profile: profile being enforced (NOT NULL, NOT unconfined)
|
||||
* @cap: capability to test if allowed
|
||||
* @audit: whether an audit record should be generated
|
||||
* @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
|
||||
* @sa: audit data (MAY BE NULL indicating no auditing)
|
||||
*
|
||||
* Returns: 0 if allowed else -EPERM
|
||||
*/
|
||||
static int profile_capable(struct aa_profile *profile, int cap, int audit,
|
||||
struct common_audit_data *sa)
|
||||
static int profile_capable(struct aa_profile *profile, int cap,
|
||||
unsigned int opts, struct common_audit_data *sa)
|
||||
{
|
||||
int error;
|
||||
|
||||
@@ -126,7 +126,7 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
|
||||
else
|
||||
error = -EPERM;
|
||||
|
||||
if (audit == SECURITY_CAP_NOAUDIT) {
|
||||
if (opts & CAP_OPT_NOAUDIT) {
|
||||
if (!COMPLAIN_MODE(profile))
|
||||
return error;
|
||||
/* audit the cap request in complain mode but note that it
|
||||
@@ -142,13 +142,13 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
|
||||
* aa_capable - test permission to use capability
|
||||
* @label: label being tested for capability (NOT NULL)
|
||||
* @cap: capability to be tested
|
||||
* @audit: whether an audit record should be generated
|
||||
* @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
|
||||
*
|
||||
* Look up capability in profile capability set.
|
||||
*
|
||||
* Returns: 0 on success, or else an error code.
|
||||
*/
|
||||
int aa_capable(struct aa_label *label, int cap, int audit)
|
||||
int aa_capable(struct aa_label *label, int cap, unsigned int opts)
|
||||
{
|
||||
struct aa_profile *profile;
|
||||
int error = 0;
|
||||
@@ -156,7 +156,7 @@ int aa_capable(struct aa_label *label, int cap, int audit)
|
||||
|
||||
sa.u.cap = cap;
|
||||
error = fn_for_each_confined(label, profile,
|
||||
profile_capable(profile, cap, audit, &sa));
|
||||
profile_capable(profile, cap, opts, &sa));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
|
||||
stack = NULL;
|
||||
break;
|
||||
}
|
||||
/* fall through to X_NAME */
|
||||
/* fall through - to X_NAME */
|
||||
case AA_X_NAME:
|
||||
if (xindex & AA_X_CHILD)
|
||||
/* released by caller */
|
||||
@@ -975,7 +975,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
|
||||
}
|
||||
aa_put_label(cred_label(bprm->cred));
|
||||
/* transfer reference, released when cred is freed */
|
||||
cred_label(bprm->cred) = new;
|
||||
set_cred_label(bprm->cred, new);
|
||||
|
||||
done:
|
||||
aa_put_label(label);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user