diff options
71 files changed, 1034 insertions, 250 deletions
diff --git a/Documentation/networking/dns_resolver.txt b/Documentation/networking/dns_resolver.txt index 7f531ad8328..d86adcdae42 100644 --- a/Documentation/networking/dns_resolver.txt +++ b/Documentation/networking/dns_resolver.txt @@ -102,6 +102,10 @@ implemented in the module can be called after doing: If _expiry is non-NULL, the expiry time (TTL) of the result will be returned also. +The kernel maintains an internal keyring in which it caches looked up keys. +This can be cleared by any process that has the CAP_SYS_ADMIN capability by +the use of KEYCTL_KEYRING_CLEAR on the keyring ID. + =============================== READING DNS KEYS FROM USERSPACE diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX index 99b85d39751..eeed1de546d 100644 --- a/Documentation/security/00-INDEX +++ b/Documentation/security/00-INDEX @@ -6,6 +6,8 @@ SELinux.txt - how to get started with the SELinux security enhancement. Smack.txt - documentation on the Smack Linux Security Module. +Yama.txt + - documentation on the Yama Linux Security Module. apparmor.txt - documentation on the AppArmor security extension. credentials.txt diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt new file mode 100644 index 00000000000..a9511f17906 --- /dev/null +++ b/Documentation/security/Yama.txt @@ -0,0 +1,65 @@ +Yama is a Linux Security Module that collects a number of system-wide DAC +security protections that are not handled by the core kernel itself. To +select it at boot time, specify "security=yama" (though this will disable +any other LSM). + +Yama is controlled through sysctl in /proc/sys/kernel/yama: + +- ptrace_scope + +============================================================== + +ptrace_scope: + +As Linux grows in popularity, it will become a larger target for +malware. One particularly troubling weakness of the Linux process +interfaces is that a single user is able to examine the memory and +running state of any of their processes. For example, if one application +(e.g. Pidgin) was compromised, it would be possible for an attacker to +attach to other running processes (e.g. Firefox, SSH sessions, GPG agent, +etc) to extract additional credentials and continue to expand the scope +of their attack without resorting to user-assisted phishing. + +This is not a theoretical problem. SSH session hijacking +(http://www.storm.net.nz/projects/7) and arbitrary code injection +(http://c-skills.blogspot.com/2007/05/injectso.html) attacks already +exist and remain possible if ptrace is allowed to operate as before. +Since ptrace is not commonly used by non-developers and non-admins, system +builders should be allowed the option to disable this debugging system. + +For a solution, some applications use prctl(PR_SET_DUMPABLE, ...) to +specifically disallow such ptrace attachment (e.g. ssh-agent), but many +do not. A more general solution is to only allow ptrace directly from a +parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still +work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID" +still work as root). + +For software that has defined application-specific relationships +between a debugging process and its inferior (crash handlers, etc), +prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which +other process (and its descendents) are allowed to call PTRACE_ATTACH +against it. Only one such declared debugging process can exists for +each inferior at a time. For example, this is used by KDE, Chromium, and +Firefox's crash handlers, and by Wine for allowing only Wine processes +to ptrace each other. If a process wishes to entirely disable these ptrace +restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...) +so that any otherwise allowed process (even those in external pid namespaces) +may attach. + +The sysctl settings are: + +0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other + process running under the same uid, as long as it is dumpable (i.e. + did not transition uids, start privileged, or have called + prctl(PR_SET_DUMPABLE...) already). + +1 - restricted ptrace: a process must have a predefined relationship + with the inferior it wants to call PTRACE_ATTACH on. By default, + this relationship is that of only its descendants when the above + classic criteria is also met. To change the relationship, an + inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare + an allowed debugger PID to call PTRACE_ATTACH on the inferior. + +The original children-only logic was based on the restrictions in grsecurity. + +============================================================== diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index fcbe7a70340..78771709142 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -554,6 +554,10 @@ The keyctl syscall functions are: process must have write permission on the keyring, and it must be a keyring (or else error ENOTDIR will result). + This function can also be used to clear special kernel keyrings if they + are appropriately marked if the user has CAP_SYS_ADMIN capability. The + DNS resolver cache keyring is an example of this. + (*) Link a key into a keyring: diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 7fc75e47e6d..a048199ce86 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -5,7 +5,6 @@ menuconfig TCG_TPM tristate "TPM Hardware Support" depends on HAS_IOMEM - depends on EXPERIMENTAL select SECURITYFS ---help--- If you have a TPM security chip in your system, which diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 32362cf35b8..ad7c7320dd1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1221,12 +1221,13 @@ ssize_t tpm_read(struct file *file, char __user *buf, ret_size = atomic_read(&chip->data_pending); atomic_set(&chip->data_pending, 0); if (ret_size > 0) { /* relay data */ + ssize_t orig_ret_size = ret_size; if (size < ret_size) ret_size = size; mutex_lock(&chip->buffer_mutex); rc = copy_to_user(buf, chip->data_buffer, ret_size); - memset(chip->data_buffer, 0, ret_size); + memset(chip->data_buffer, 0, orig_ret_size); if (rc) ret_size = -EFAULT; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 01054713828..b1c5280ac15 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -99,6 +99,8 @@ struct tpm_vendor_specific { wait_queue_head_t int_queue; }; +#define TPM_VID_INTEL 0x8086 + struct tpm_chip { struct device *dev; /* Device stuff */ diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 70fac9abb0e..d2a70cae76d 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -367,7 +367,12 @@ static int probe_itpm(struct tpm_chip *chip) 0x00, 0x00, 0x00, 0xf1 }; size_t len = sizeof(cmd_getticks); - int rem_itpm = itpm; + bool rem_itpm = itpm; + u16 vendor = ioread16(chip->vendor.iobase + TPM_DID_VID(0)); + + /* probe only iTPMS */ + if (vendor != TPM_VID_INTEL) + return 0; itpm = 0; @@ -390,9 +395,6 @@ static int probe_itpm(struct tpm_chip *chip) out: itpm = rem_itpm; tpm_tis_ready(chip); - /* some TPMs need a break here otherwise they will not work - * correctly on the immediately subsequent command */ - msleep(chip->vendor.timeout_b); release_locality(chip, chip->vendor.locality, 0); return rc; @@ -508,7 +510,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, resource_size_t len, unsigned int irq) { u32 vendor, intfcaps, intmask; - int rc, i, irq_s, irq_e; + int rc, i, irq_s, irq_e, probe; struct tpm_chip *chip; if (!(chip = tpm_register_hardware(dev, &tpm_tis))) @@ -538,11 +540,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); if (!itpm) { - itpm = probe_itpm(chip); - if (itpm < 0) { + probe = probe_itpm(chip); + if (probe < 0) { rc = -ENODEV; goto out_err; } + itpm = (probe == 0) ? 0 : 1; } if (itpm) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 58dc117a8d7..0427c6561c8 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/wait.h> #include <linux/cdev.h> +#include <linux/idr.h> #include <linux/fs.h> #include <net/net_namespace.h> diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 501b27c1814..1c6f700f5fa 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -23,6 +23,7 @@ #include <linux/crypto.h> #include <linux/completion.h> #include <linux/module.h> +#include <linux/idr.h> #include <asm/unaligned.h> #include <scsi/scsi_device.h> #include <scsi/iscsi_proto.h> diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 38cb7ce8469..1ee33a8c3fa 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -21,6 +21,7 @@ #include <linux/string.h> #include <linux/kthread.h> #include <linux/crypto.h> +#include <linux/idr.h> #include <scsi/iscsi_proto.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c1b25448738..3cc1b251ca0 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -556,6 +556,7 @@ init_cifs_idmap(void) /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; root_cred = cred; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 31778f74357..d4f772ebd1e 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -36,6 +36,7 @@ #include <linux/inet.h> #include <linux/in6.h> #include <linux/slab.h> +#include <linux/idr.h> #include <net/ipv6.h> #include <linux/nfs_xdr.h> #include <linux/sunrpc/bc_xprt.h> diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 2c05f1991e1..a1bbf7780df 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -198,6 +198,7 @@ int nfs_idmap_init(void) if (ret < 0) goto failed_put_key; + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index a6b62173d4c..67bbf6e4e19 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -6,7 +6,9 @@ #include <linux/poll.h> #include <linux/proc_fs.h> #include <linux/security.h> +#include <linux/sched.h> #include <linux/namei.h> +#include <linux/mm.h> #include "internal.h" static const struct dentry_operations proc_sys_dentry_operations; diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 46741970371..8b4f12b33f5 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -71,6 +71,7 @@ #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/security.h> +#include <linux/sched.h> #include <linux/kmod.h> #include <linux/namei.h> #include <linux/capability.h> diff --git a/fs/super.c b/fs/super.c index 6277ec6cb60..d90e900a8a0 100644 --- a/fs/super.c +++ b/fs/super.c @@ -32,6 +32,7 @@ #include <linux/backing-dev.h> #include <linux/rculist_bl.h> #include <linux/cleancache.h> +#include <linux/fsnotify.h> #include "internal.h" diff --git a/include/linux/key.h b/include/linux/key.h index 5253471cd2e..1600ebf717a 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -155,6 +155,7 @@ struct key { #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ #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 */ /* the description string * - this is used to match a key against search criteria diff --git a/include/linux/prctl.h b/include/linux/prctl.h index 7ddc7f1b480..a0413ac3abe 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -114,4 +114,11 @@ # define PR_SET_MM_START_BRK 6 # define PR_SET_MM_BRK 7 +/* + * Set specific pid that is allowed to ptrace the current task. + * A value of 0 mean "no process". + */ +#define PR_SET_PTRACER 0x59616d61 +# define PR_SET_PTRACER_ANY ((unsigned long)-1) + #endif /* _LINUX_PRCTL_H */ diff --git a/include/linux/security.h b/include/linux/security.h index c8949385e56..673afbb8238 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -22,22 +22,36 @@ #ifndef __LINUX_SECURITY_H #define __LINUX_SECURITY_H -#include <linux/fs.h> -#include <linux/fsnotify.h> -#include <linux/binfmts.h> -#include <linux/dcache.h> -#include <linux/signal.h> -#include <linux/resource.h> -#include <linux/sem.h> -#include <linux/shm.h> -#include <linux/mm.h> /* PAGE_ALIGN */ -#include <linux/msg.h> -#include <linux/sched.h> #include <linux/key.h> -#include <linux/xfrm.h> +#include <linux/capability.h> #include <linux/slab.h> -#include <linux/xattr.h> -#include <net/flow.h> +#include <linux/err.h> + +struct linux_binprm; +struct cred; +struct rlimit; +struct siginfo; +struct sem_array; +struct sembuf; +struct kern_ipc_perm; +struct audit_context; +struct super_block; +struct inode; +struct dentry; +struct file; +struct vfsmount; +struct path; +struct qstr; +struct nameidata; +struct iattr; +struct fown_struct; +struct file_operations; +struct shmid_kernel; +struct msg_msg; +struct msg_queue; +struct xattr; +struct xfrm_sec_ctx; +struct mm_struct; /* Maximum number of letters for an LSM name string */ #define SECURITY_NAME_MAX 10 @@ -49,6 +63,7 @@ struct ctl_table; struct audit_krule; struct user_namespace; +struct timezone; /* * These functions are in security/capability.c and are used @@ -131,18 +146,6 @@ struct request_sock; #define LSM_UNSAFE_PTRACE_CAP 4 #ifdef CONFIG_MMU -/* - * If a hint addr is less than mmap_min_addr change hint to be as - * low as possible but still greater than mmap_min_addr - */ -static inline unsigned long round_hint_to_min(unsigned long hint) -{ - hint &= PAGE_MASK; - if (((void *)hint != NULL) && - (hint < mmap_min_addr)) - return PAGE_ALIGN(mmap_min_addr); - return hint; -} extern int mmap_min_addr_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); #endif @@ -651,6 +654,10 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * manual page for definitions of the @clone_flags. * @clone_flags contains the flags indicating what should be shared. * Return 0 if permission is granted. + * @task_free: + * @task task being freed + * Handle release of task-related resources. (Note that this can be called + * from interrupt context.) * @cred_alloc_blank: * @cred points to the credentials. * @gfp indicates the atomicity of any memory allocations. @@ -1493,6 +1500,7 @@ struct security_operations { int (*dentry_open) (struct file *file, const struct cred *cred); int (*task_create) (unsigned long clone_flags); + void (*task_free) (struct task_struct *task); int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp); void (*cred_free) (struct cred *cred); int (*cred_prepare)(struct cred *new, const struct cred *old, @@ -1674,9 +1682,7 @@ 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); int security_settime(const struct timespec *ts, const struct timezone *tz); -int security_vm_enough_memory(long pages); int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); -int security_vm_enough_memory_kern(long pages); int security_bprm_set_creds(struct linux_binprm *bprm); int security_bprm_check(struct linux_binprm *bprm); void security_bprm_committing_creds(struct linux_binprm *bprm); @@ -1752,6 +1758,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, int security_file_receive(struct file *file); int security_dentry_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); void security_cred_free(struct cred *cred); int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); @@ -1896,25 +1903,11 @@ static inline int security_settime(const struct timespec *ts, < |