Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"New notable features:
- The seccomp work from Will Drewry
- PR_{GET,SET}_NO_NEW_PRIVS from Andy Lutomirski
- Longer security labels for Smack from Casey Schaufler
- Additional ptrace restriction modes for Yama by Kees Cook"
Fix up trivial context conflicts in arch/x86/Kconfig and include/linux/filter.h
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (65 commits)
apparmor: fix long path failure due to disconnected path
apparmor: fix profile lookup for unconfined
ima: fix filename hint to reflect script interpreter name
KEYS: Don't check for NULL key pointer in key_validate()
Smack: allow for significantly longer Smack labels v4
gfp flags for security_inode_alloc()?
Smack: recursive tramsmute
Yama: replace capable() with ns_capable()
TOMOYO: Accept manager programs which do not start with / .
KEYS: Add invalidation support
KEYS: Do LRU discard in full keyrings
KEYS: Permit in-place link replacement in keyring list
KEYS: Perform RCU synchronisation on keys prior to key destruction
KEYS: Announce key type (un)registration
KEYS: Reorganise keys Makefile
KEYS: Move the key config into security/keys/Kconfig
KEYS: Use the compat keyctl() syscall wrapper on Sparc64 for Sparc32 compat
Yama: remove an unused variable
samples/seccomp: fix dependencies on arch macros
Yama: add additional ptrace scopes
...
This commit is contained in:
commit
cb60e3e65c
102 changed files with 3687 additions and 1239 deletions
|
|
@ -330,6 +330,7 @@ header-y += scc.h
|
|||
header-y += sched.h
|
||||
header-y += screen_info.h
|
||||
header-y += sdla.h
|
||||
header-y += seccomp.h
|
||||
header-y += securebits.h
|
||||
header-y += selinux_netlink.h
|
||||
header-y += sem.h
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ extern void audit_putname(const char *name);
|
|||
extern void __audit_inode(const char *name, const struct dentry *dentry);
|
||||
extern void __audit_inode_child(const struct dentry *dentry,
|
||||
const struct inode *parent);
|
||||
extern void __audit_seccomp(unsigned long syscall);
|
||||
extern void __audit_seccomp(unsigned long syscall, long signr, int code);
|
||||
extern void __audit_ptrace(struct task_struct *t);
|
||||
|
||||
static inline int audit_dummy_context(void)
|
||||
|
|
@ -508,10 +508,10 @@ static inline void audit_inode_child(const struct dentry *dentry,
|
|||
}
|
||||
void audit_core_dumps(long signr);
|
||||
|
||||
static inline void audit_seccomp(unsigned long syscall)
|
||||
static inline void audit_seccomp(unsigned long syscall, long signr, int code)
|
||||
{
|
||||
if (unlikely(!audit_dummy_context()))
|
||||
__audit_seccomp(syscall);
|
||||
__audit_seccomp(syscall, signr, code);
|
||||
}
|
||||
|
||||
static inline void audit_ptrace(struct task_struct *t)
|
||||
|
|
@ -634,7 +634,7 @@ extern int audit_signals;
|
|||
#define audit_inode(n,d) do { (void)(d); } while (0)
|
||||
#define audit_inode_child(i,p) do { ; } while (0)
|
||||
#define audit_core_dumps(i) do { ; } while (0)
|
||||
#define audit_seccomp(i) do { ; } while (0)
|
||||
#define audit_seccomp(i,s,c) do { ; } while (0)
|
||||
#define auditsc_get_stamp(c,t,s) (0)
|
||||
#define audit_get_loginuid(t) (-1)
|
||||
#define audit_get_sessionid(t) (-1)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/compat.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -133,6 +134,16 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
* A struct sock_filter is architecture independent.
|
||||
*/
|
||||
struct compat_sock_fprog {
|
||||
u16 len;
|
||||
compat_uptr_t filter; /* struct sock_filter * */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct sk_buff;
|
||||
struct sock;
|
||||
|
||||
|
|
@ -233,6 +244,7 @@ enum {
|
|||
BPF_S_ANC_RXHASH,
|
||||
BPF_S_ANC_CPU,
|
||||
BPF_S_ANC_ALU_XOR_X,
|
||||
BPF_S_ANC_SECCOMP_LD_W,
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
|||
|
|
@ -124,7 +124,10 @@ static inline unsigned long is_key_possessed(const key_ref_t key_ref)
|
|||
struct key {
|
||||
atomic_t usage; /* number of references */
|
||||
key_serial_t serial; /* key serial number */
|
||||
struct rb_node serial_node;
|
||||
union {
|
||||
struct list_head graveyard_link;
|
||||
struct rb_node serial_node;
|
||||
};
|
||||
struct key_type *type; /* type of key */
|
||||
struct rw_semaphore sem; /* change vs change sem */
|
||||
struct key_user *user; /* owner of this key */
|
||||
|
|
@ -133,6 +136,7 @@ struct key {
|
|||
time_t expiry; /* time at which key expires (or 0) */
|
||||
time_t revoked_at; /* time at which key was revoked */
|
||||
};
|
||||
time_t last_used_at; /* last time used for LRU keyring discard */
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
key_perm_t perm; /* access permissions */
|
||||
|
|
@ -156,6 +160,7 @@ struct key {
|
|||
#define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */
|
||||
#define KEY_FLAG_NEGATIVE 5 /* set if key is negative */
|
||||
#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
|
||||
#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
|
||||
|
||||
/* the description string
|
||||
* - this is used to match a key against search criteria
|
||||
|
|
@ -199,6 +204,7 @@ extern struct key *key_alloc(struct key_type *type,
|
|||
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
|
||||
|
||||
extern void key_revoke(struct key *key);
|
||||
extern void key_invalidate(struct key *key);
|
||||
extern void key_put(struct key *key);
|
||||
|
||||
static inline struct key *key_get(struct key *key)
|
||||
|
|
@ -236,7 +242,7 @@ extern struct key *request_key_async_with_auxdata(struct key_type *type,
|
|||
|
||||
extern int wait_for_key_construction(struct key *key, bool intr);
|
||||
|
||||
extern int key_validate(struct key *key);
|
||||
extern int key_validate(const struct key *key);
|
||||
|
||||
extern key_ref_t key_create_or_update(key_ref_t keyring,
|
||||
const char *type,
|
||||
|
|
@ -319,6 +325,7 @@ extern void key_init(void);
|
|||
#define key_serial(k) 0
|
||||
#define key_get(k) ({ NULL; })
|
||||
#define key_revoke(k) do { } while(0)
|
||||
#define key_invalidate(k) do { } while(0)
|
||||
#define key_put(k) do { } while(0)
|
||||
#define key_ref_put(k) do { } while(0)
|
||||
#define make_key_ref(k, p) NULL
|
||||
|
|
|
|||
|
|
@ -55,5 +55,6 @@
|
|||
#define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */
|
||||
#define KEYCTL_REJECT 19 /* reject a partially constructed key */
|
||||
#define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */
|
||||
#define KEYCTL_INVALIDATE 21 /* invalidate a key */
|
||||
|
||||
#endif /* _LINUX_KEYCTL_H */
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ struct common_audit_data {
|
|||
#define LSM_AUDIT_DATA_KMOD 8
|
||||
#define LSM_AUDIT_DATA_INODE 9
|
||||
#define LSM_AUDIT_DATA_DENTRY 10
|
||||
struct task_struct *tsk;
|
||||
union {
|
||||
struct path path;
|
||||
struct dentry *dentry;
|
||||
|
|
@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
|||
int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
||||
struct common_audit_data *ad, u8 *proto);
|
||||
|
||||
/* Initialize an LSM audit data structure. */
|
||||
#define COMMON_AUDIT_DATA_INIT(_d, _t) \
|
||||
{ memset((_d), 0, sizeof(struct common_audit_data)); \
|
||||
(_d)->type = LSM_AUDIT_DATA_##_t; }
|
||||
|
||||
void common_lsm_audit(struct common_audit_data *a,
|
||||
void (*pre_audit)(struct audit_buffer *, void *),
|
||||
void (*post_audit)(struct audit_buffer *, void *));
|
||||
|
|
|
|||
|
|
@ -124,4 +124,19 @@
|
|||
#define PR_SET_CHILD_SUBREAPER 36
|
||||
#define PR_GET_CHILD_SUBREAPER 37
|
||||
|
||||
/*
|
||||
* If no_new_privs is set, then operations that grant new privileges (i.e.
|
||||
* execve) will either fail or not grant them. This affects suid/sgid,
|
||||
* file capabilities, and LSMs.
|
||||
*
|
||||
* Operations that merely manipulate or drop existing privileges (setresuid,
|
||||
* capset, etc.) will still work. Drop those privileges if you want them gone.
|
||||
*
|
||||
* Changing LSM security domain is considered a new privilege. So, for example,
|
||||
* asking selinux for a specific new context (e.g. with runcon) will result
|
||||
* in execve returning -EPERM.
|
||||
*/
|
||||
#define PR_SET_NO_NEW_PRIVS 38
|
||||
#define PR_GET_NO_NEW_PRIVS 39
|
||||
|
||||
#endif /* _LINUX_PRCTL_H */
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
#define PTRACE_EVENT_EXEC 4
|
||||
#define PTRACE_EVENT_VFORK_DONE 5
|
||||
#define PTRACE_EVENT_EXIT 6
|
||||
#define PTRACE_EVENT_SECCOMP 7
|
||||
/* Extended result codes which enabled by means other than options. */
|
||||
#define PTRACE_EVENT_STOP 128
|
||||
|
||||
|
|
@ -69,8 +70,9 @@
|
|||
#define PTRACE_O_TRACEEXEC (1 << PTRACE_EVENT_EXEC)
|
||||
#define PTRACE_O_TRACEVFORKDONE (1 << PTRACE_EVENT_VFORK_DONE)
|
||||
#define PTRACE_O_TRACEEXIT (1 << PTRACE_EVENT_EXIT)
|
||||
#define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP)
|
||||
|
||||
#define PTRACE_O_MASK 0x0000007f
|
||||
#define PTRACE_O_MASK 0x000000ff
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
|
|
@ -98,6 +100,7 @@
|
|||
#define PT_TRACE_EXEC PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
|
||||
#define PT_TRACE_VFORK_DONE PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
|
||||
#define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
|
||||
#define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)
|
||||
|
||||
/* single stepping state bits (used on ARM and PA-RISC) */
|
||||
#define PT_SINGLESTEP_BIT 31
|
||||
|
|
|
|||
|
|
@ -1341,6 +1341,8 @@ struct task_struct {
|
|||
* execve */
|
||||
unsigned in_iowait:1;
|
||||
|
||||
/* task may not gain privileges */
|
||||
unsigned no_new_privs:1;
|
||||
|
||||
/* Revert to default priority/policy when forking */
|
||||
unsigned sched_reset_on_fork:1;
|
||||
|
|
@ -1450,7 +1452,7 @@ struct task_struct {
|
|||
uid_t loginuid;
|
||||
unsigned int sessionid;
|
||||
#endif
|
||||
seccomp_t seccomp;
|
||||
struct seccomp seccomp;
|
||||
|
||||
/* Thread group tracking */
|
||||
u32 parent_exec_id;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,90 @@
|
|||
#ifndef _LINUX_SECCOMP_H
|
||||
#define _LINUX_SECCOMP_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
|
||||
#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
|
||||
#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
|
||||
#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
|
||||
|
||||
/*
|
||||
* All BPF programs must return a 32-bit value.
|
||||
* The bottom 16-bits are for optional return data.
|
||||
* The upper 16-bits are ordered from least permissive values to most.
|
||||
*
|
||||
* The ordering ensures that a min_t() over composed return values always
|
||||
* selects the least permissive choice.
|
||||
*/
|
||||
#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
|
||||
#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
|
||||
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
|
||||
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
|
||||
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
||||
|
||||
/* Masks for the return value sections. */
|
||||
#define SECCOMP_RET_ACTION 0x7fff0000U
|
||||
#define SECCOMP_RET_DATA 0x0000ffffU
|
||||
|
||||
/**
|
||||
* struct seccomp_data - the format the BPF program executes over.
|
||||
* @nr: the system call number
|
||||
* @arch: indicates system call convention as an AUDIT_ARCH_* value
|
||||
* as defined in <linux/audit.h>.
|
||||
* @instruction_pointer: at the time of the system call.
|
||||
* @args: up to 6 system call arguments always stored as 64-bit values
|
||||
* regardless of the architecture.
|
||||
*/
|
||||
struct seccomp_data {
|
||||
int nr;
|
||||
__u32 arch;
|
||||
__u64 instruction_pointer;
|
||||
__u64 args[6];
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_SECCOMP
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
#include <asm/seccomp.h>
|
||||
|
||||
typedef struct { int mode; } seccomp_t;
|
||||
struct seccomp_filter;
|
||||
/**
|
||||
* struct seccomp - the state of a seccomp'ed process
|
||||
*
|
||||
* @mode: indicates one of the valid values above for controlled
|
||||
* system calls available to a process.
|
||||
* @filter: The metadata and ruleset for determining what system calls
|
||||
* are allowed for a task.
|
||||
*
|
||||
* @filter must only be accessed from the context of current as there
|
||||
* is no locking.
|
||||
*/
|
||||
struct seccomp {
|
||||
int mode;
|
||||
struct seccomp_filter *filter;
|
||||
};
|
||||
|
||||
extern void __secure_computing(int);
|
||||
static inline void secure_computing(int this_syscall)
|
||||
extern int __secure_computing(int);
|
||||
static inline int secure_computing(int this_syscall)
|
||||
{
|
||||
if (unlikely(test_thread_flag(TIF_SECCOMP)))
|
||||
__secure_computing(this_syscall);
|
||||
return __secure_computing(this_syscall);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A wrapper for architectures supporting only SECCOMP_MODE_STRICT. */
|
||||
static inline void secure_computing_strict(int this_syscall)
|
||||
{
|
||||
BUG_ON(secure_computing(this_syscall) != 0);
|
||||
}
|
||||
|
||||
extern long prctl_get_seccomp(void);
|
||||
extern long prctl_set_seccomp(unsigned long);
|
||||
extern long prctl_set_seccomp(unsigned long, char __user *);
|
||||
|
||||
static inline int seccomp_mode(seccomp_t *s)
|
||||
static inline int seccomp_mode(struct seccomp *s)
|
||||
{
|
||||
return s->mode;
|
||||
}
|
||||
|
|
@ -28,25 +93,41 @@ static inline int seccomp_mode(seccomp_t *s)
|
|||
|
||||
#include <linux/errno.h>
|
||||
|
||||
typedef struct { } seccomp_t;
|
||||
struct seccomp { };
|
||||
struct seccomp_filter { };
|
||||
|
||||
#define secure_computing(x) do { } while (0)
|
||||
static inline int secure_computing(int this_syscall) { return 0; }
|
||||
static inline void secure_computing_strict(int this_syscall) { return; }
|
||||
|
||||
static inline long prctl_get_seccomp(void)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline long prctl_set_seccomp(unsigned long arg2)
|
||||
static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int seccomp_mode(seccomp_t *s)
|
||||
static inline int seccomp_mode(struct seccomp *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SECCOMP */
|
||||
|
||||
#ifdef CONFIG_SECCOMP_FILTER
|
||||
extern void put_seccomp_filter(struct task_struct *tsk);
|
||||
extern void get_seccomp_filter(struct task_struct *tsk);
|
||||
extern u32 seccomp_bpf_load(int off);
|
||||
#else /* CONFIG_SECCOMP_FILTER */
|
||||
static inline void put_seccomp_filter(struct task_struct *tsk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static inline void get_seccomp_filter(struct task_struct *tsk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_SECCOMP_FILTER */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SECCOMP_H */
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ struct request_sock;
|
|||
#define LSM_UNSAFE_SHARE 1
|
||||
#define LSM_UNSAFE_PTRACE 2
|
||||
#define LSM_UNSAFE_PTRACE_CAP 4
|
||||
#define LSM_UNSAFE_NO_NEW_PRIVS 8
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
extern int mmap_min_addr_handler(struct ctl_table *table, int write,
|
||||
|
|
@ -639,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
|||
* to receive an open file descriptor via socket IPC.
|
||||
* @file contains the file structure being received.
|
||||
* Return 0 if permission is granted.
|
||||
*
|
||||
* Security hook for dentry
|
||||
*
|
||||
* @dentry_open
|
||||
* @file_open
|
||||
* Save open-time permission checking state for later use upon
|
||||
* file_permission, and recheck access if anything has changed
|
||||
* since inode_permission.
|
||||
|
|
@ -1497,7 +1495,7 @@ struct security_operations {
|
|||
int (*file_send_sigiotask) (struct task_struct *tsk,
|
||||
struct fown_struct *fown, int sig);
|
||||
int (*file_receive) (struct file *file);
|
||||
int (*dentry_open) (struct file *file, const struct cred *cred);
|
||||
int (*file_open) (struct file *file, const struct cred *cred);
|
||||
|
||||
int (*task_create) (unsigned long clone_flags);
|
||||
void (*task_free) (struct task_struct *task);
|
||||
|
|
@ -1756,7 +1754,7 @@ int security_file_set_fowner(struct file *file);
|
|||
int security_file_send_sigiotask(struct task_struct *tsk,
|
||||
struct fown_struct *fown, int sig);
|
||||
int security_file_receive(struct file *file);
|
||||
int security_dentry_open(struct file *file, const struct cred *cred);
|
||||
int security_file_open(struct file *file, const struct cred *cred);
|
||||
int security_task_create(unsigned long clone_flags);
|
||||
void security_task_free(struct task_struct *task);
|
||||
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
|
||||
|
|
@ -2227,8 +2225,8 @@ static inline int security_file_receive(struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_dentry_open(struct file *file,
|
||||
const struct cred *cred)
|
||||
static inline int security_file_open(struct file *file,
|
||||
const struct cred *cred)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue