Commit 3296ca27 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of...

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (44 commits)
  nommu: Provide mmap_min_addr definition.
  TOMOYO: Add description of lists and structures.
  TOMOYO: Remove unused field.
  integrity: ima audit dentry_open failure
  TOMOYO: Remove unused parameter.
  security: use mmap_min_addr indepedently of security models
  TOMOYO: Simplify policy reader.
  TOMOYO: Remove redundant markers.
  SELinux: define audit permissions for audit tree netlink messages
  TOMOYO: Remove unused mutex.
  tomoyo: avoid get+put of task_struct
  smack: Remove redundant initialization.
  integrity: nfsd imbalance bug fix
  rootplug: Remove redundant initialization.
  smack: do not beyond ARRAY_SIZE of data
  integrity: move ima_counts_get
  integrity: path_check update
  IMA: Add __init notation to ima functions
  IMA: Minimal IMA policy and boot param for TCB IMA policy
  selinux: remove obsolete read buffer limit from sel_read_bool
  ...
parents e893123c 73fbad28
......@@ -184,8 +184,9 @@ length. Single character labels using special characters, that being anything
other than a letter or digit, are reserved for use by the Smack development
team. Smack labels are unstructured, case sensitive, and the only operation
ever performed on them is comparison for equality. Smack labels cannot
contain unprintable characters or the "/" (slash) character. Smack labels
cannot begin with a '-', which is reserved for special options.
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
(quote) and '"' (double-quote) characters.
Smack labels cannot begin with a '-', which is reserved for special options.
There are some predefined labels:
......@@ -523,3 +524,18 @@ Smack supports some mount options:
These mount options apply to all file system types.
Smack auditing
If you want Smack auditing of security events, you need to set CONFIG_AUDIT
in your kernel configuration.
By default, all denied events will be audited. You can change this behavior by
writing a single character to the /smack/logging file :
0 : no logging
1 : log denied (default)
2 : log accepted
3 : log denied & accepted
Events are logged as 'key=value' pairs, for each event you at least will get
the subjet, the object, the rights requested, the action, the kernel function
that triggered the event, plus other pairs depending on the type of event
audited.
......@@ -928,6 +928,12 @@ and is between 256 and 4096 characters. It is defined in the file
Formt: { "sha1" | "md5" }
default: "sha1"
ima_tcb [IMA]
Load a policy which meets the needs of the Trusted
Computing Base. This means IMA will measure all
programs exec'd, files mmap'd for exec, and all files
opened for read by uid=0.
in2000= [HW,SCSI]
See header of drivers/scsi/in2000.c.
......
......@@ -32,6 +32,7 @@ show up in /proc/sys/kernel:
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
- modprobe ==> Documentation/debugging-modules.txt
- modules_disabled
- msgmax
- msgmnb
- msgmni
......@@ -184,6 +185,16 @@ kernel stack.
==============================================================
modules_disabled:
A toggle value indicating if modules are allowed to be loaded
in an otherwise modular kernel. This toggle defaults to off
(0), but can be set true (1). Once true, modules can be
neither loaded nor unloaded, and the toggle cannot be set back
to false.
==============================================================
osrelease, ostype & version:
# cat osrelease
......
......@@ -1488,7 +1488,7 @@ int compat_do_execve(char * filename,
if (!bprm)
goto out_files;
retval = mutex_lock_interruptible(&current->cred_exec_mutex);
retval = mutex_lock_interruptible(&current->cred_guard_mutex);
if (retval < 0)
goto out_free;
current->in_execve = 1;
......@@ -1550,7 +1550,7 @@ int compat_do_execve(char * filename,
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);
mutex_unlock(&current->cred_guard_mutex);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
......@@ -1573,7 +1573,7 @@ int compat_do_execve(char * filename,
out_unlock:
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);
mutex_unlock(&current->cred_guard_mutex);
out_free:
free_bprm(bprm);
......
......@@ -1016,7 +1016,7 @@ void install_exec_creds(struct linux_binprm *bprm)
commit_creds(bprm->cred);
bprm->cred = NULL;
/* cred_exec_mutex must be held at least to this point to prevent
/* cred_guard_mutex must be held at least to this point to prevent
* ptrace_attach() from altering our determination of the task's
* credentials; any time after this it may be unlocked */
......@@ -1026,7 +1026,7 @@ EXPORT_SYMBOL(install_exec_creds);
/*
* determine how safe it is to execute the proposed program
* - the caller must hold current->cred_exec_mutex to protect against
* - the caller must hold current->cred_guard_mutex to protect against
* PTRACE_ATTACH
*/
int check_unsafe_exec(struct linux_binprm *bprm)
......@@ -1268,7 +1268,7 @@ int do_execve(char * filename,
if (!bprm)
goto out_files;
retval = mutex_lock_interruptible(&current->cred_exec_mutex);
retval = mutex_lock_interruptible(&current->cred_guard_mutex);
if (retval < 0)
goto out_free;
current->in_execve = 1;
......@@ -1331,7 +1331,7 @@ int do_execve(char * filename,
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);
mutex_unlock(&current->cred_guard_mutex);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
......@@ -1354,7 +1354,7 @@ int do_execve(char * filename,
out_unlock:
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);
mutex_unlock(&current->cred_guard_mutex);
out_free:
free_bprm(bprm);
......
......@@ -30,6 +30,7 @@
#include <linux/dnotify.h>
#include <linux/statfs.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <asm/uaccess.h>
......@@ -986,6 +987,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag)
&hugetlbfs_file_operations);
if (!file)
goto out_dentry; /* inode is already attached */
ima_counts_get(file);
return file;
......
......@@ -853,7 +853,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
err = inode_permission(nd->path.dentry->d_inode,
MAY_EXEC);
if (!err)
err = ima_path_check(&nd->path, MAY_EXEC);
err = ima_path_check(&nd->path, MAY_EXEC,
IMA_COUNT_UPDATE);
if (err)
break;
......@@ -1515,7 +1516,8 @@ int may_open(struct path *path, int acc_mode, int flag)
return error;
error = ima_path_check(path,
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC),
IMA_COUNT_UPDATE);
if (error)
return error;
/*
......
......@@ -55,6 +55,7 @@
#include <linux/security.h>
#endif /* CONFIG_NFSD_V4 */
#include <linux/jhash.h>
#include <linux/ima.h>
#include <asm/uaccess.h>
......@@ -735,6 +736,8 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
flags, cred);
if (IS_ERR(*filp))
host_err = PTR_ERR(*filp);
else
ima_counts_get(*filp);
out_nfserr:
err = nfserrno(host_err);
out:
......@@ -2024,6 +2027,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
struct dentry *dentry, int acc)
{
struct inode *inode = dentry->d_inode;
struct path path;
int err;
if (acc == NFSD_MAY_NOP)
......@@ -2096,7 +2100,17 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
if (err == -EACCES && S_ISREG(inode->i_mode) &&
acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
err = inode_permission(inode, MAY_EXEC);
if (err)
goto nfsd_out;
/* Do integrity (permission) checking now, but defer incrementing
* IMA counts to the actual file open.
*/
path.mnt = exp->ex_path.mnt;
path.dentry = dentry;
err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
IMA_COUNT_LEAVE);
nfsd_out:
return err? nfserrno(err) : 0;
}
......
......@@ -2128,9 +2128,15 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
if (copy_from_user(page, buf, count))
goto out_free;
/* Guard against adverse ptrace interaction */
length = mutex_lock_interruptible(&task->cred_guard_mutex);
if (length < 0)
goto out_free;
length = security_setprocattr(task,
(char*)file->f_path.dentry->d_name.name,
(void*)page, count);
mutex_unlock(&task->cred_guard_mutex);
out_free:
free_page((unsigned long) page);
out:
......
......@@ -13,14 +13,17 @@
#include <linux/fs.h>
struct linux_binprm;
#define IMA_COUNT_UPDATE 1
#define IMA_COUNT_LEAVE 0
#ifdef CONFIG_IMA
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_inode_alloc(struct inode *inode);
extern void ima_inode_free(struct inode *inode);
extern int ima_path_check(struct path *path, int mask);
extern int ima_path_check(struct path *path, int mask, int update_counts);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern void ima_shm_check(struct file *file);
extern void ima_counts_get(struct file *file);
#else
static inline int ima_bprm_check(struct linux_binprm *bprm)
......@@ -38,7 +41,7 @@ static inline void ima_inode_free(struct inode *inode)
return;
}
static inline int ima_path_check(struct path *path, int mask)
static inline int ima_path_check(struct path *path, int mask, int update_counts)
{
return 0;
}
......@@ -53,7 +56,7 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
return 0;
}
static inline void ima_shm_check(struct file *file)
static inline void ima_counts_get(struct file *file)
{
return;
}
......
......@@ -145,8 +145,8 @@ extern struct cred init_cred;
.group_leader = &tsk, \
.real_cred = &init_cred, \
.cred = &init_cred, \
.cred_exec_mutex = \
__MUTEX_INITIALIZER(tsk.cred_exec_mutex), \
.cred_guard_mutex = \
__MUTEX_INITIALIZER(tsk.cred_guard_mutex), \
.comm = "swapper", \
.thread = INIT_THREAD, \
.fs = &init_fs, \
......
/*
* Common LSM logging functions
* Heavily borrowed from selinux/avc.h
*
* Author : Etienne BASSET <etienne.basset@ensta.org>
*
* All credits to : Stephen Smalley, <sds@epoch.ncsc.mil>
* All BUGS to : Etienne BASSET <etienne.basset@ensta.org>
*/
#ifndef _LSM_COMMON_LOGGING_
#define _LSM_COMMON_LOGGING_
#include <linux/stddef.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/audit.h>
#include <linux/in6.h>
#include <linux/path.h>
#include <linux/key.h>
#include <linux/skbuff.h>
#include <asm/system.h>
/* Auxiliary data to use in generating the audit record. */
struct common_audit_data {
char type;
#define LSM_AUDIT_DATA_FS 1
#define LSM_AUDIT_DATA_NET 2
#define LSM_AUDIT_DATA_CAP 3
#define LSM_AUDIT_DATA_IPC 4
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
struct task_struct *tsk;
union {
struct {
struct path path;
struct inode *inode;
} fs;
struct {
int netif;
struct sock *sk;
u16 family;
__be16 dport;
__be16 sport;
union {
struct {
__be32 daddr;
__be32 saddr;
} v4;
struct {
struct in6_addr daddr;
struct in6_addr saddr;
} v6;
} fam;
} net;
int cap;
int ipc_id;
struct task_struct *tsk;
#ifdef CONFIG_KEYS
struct {
key_serial_t key;
char *key_desc;
} key_struct;
#endif
} u;
const char *function;
/* this union contains LSM specific data */
union {
/* SMACK data */
struct smack_audit_data {
char *subject;
char *object;
char *request;
int result;
} smack_audit_data;
/* SELinux data */
struct {
u32 ssid;
u32 tsid;
u16 tclass;
u32 requested;
u32 audited;
struct av_decision *avd;
int result;
} selinux_audit_data;
} lsm_priv;
/* these callback will be implemented by a specific LSM */
void (*lsm_pre_audit)(struct audit_buffer *, void *);
void (*lsm_post_audit)(struct audit_buffer *, void *);
};
#define v4info fam.v4
#define v6info fam.v6
int ipv4_skb_to_auditdata(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto);
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; (_d)->function = __func__; }
void common_lsm_audit(struct common_audit_data *a);
#endif
......@@ -9,6 +9,7 @@
#define DEBUGFS_MAGIC 0x64626720
#define SYSFS_MAGIC 0x62656572
#define SECURITYFS_MAGIC 0x73636673
#define SELINUX_MAGIC 0xf97cff8c
#define TMPFS_MAGIC 0x01021994
#define SQUASHFS_MAGIC 0x73717368
#define EFS_SUPER_MAGIC 0x414A53
......
......@@ -581,12 +581,10 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
*/
static inline unsigned long round_hint_to_min(unsigned long hint)
{
#ifdef CONFIG_SECURITY
hint &= PAGE_MASK;
if (((void *)hint != NULL) &&
(hint < mmap_min_addr))
return PAGE_ALIGN(mmap_min_addr);
#endif
return hint;
}
......
......@@ -1261,7 +1261,9 @@ struct task_struct {
* credentials (COW) */
const struct cred *cred; /* effective (overridable) subjective task
* credentials (COW) */
struct mutex cred_exec_mutex; /* execve vs ptrace cred calculation mutex */
struct mutex cred_guard_mutex; /* guard against foreign influences on
* credential calculations
* (notably. ptrace) */
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
......@@ -1901,6 +1903,7 @@ extern void sched_dead(struct task_struct *p);
extern void proc_caches_init(void);
extern void flush_signals(struct task_struct *);
extern void __flush_signals(struct task_struct *);
extern void ignore_signals(struct task_struct *);
extern void flush_signal_handlers(struct task_struct *, int force_default);
extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info);
......
......@@ -2197,6 +2197,8 @@ static inline int security_file_mmap(struct file *file, unsigned long reqprot,
unsigned long addr,
unsigned long addr_only)
{
if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
return -EACCES;
return 0;
}
......
......@@ -384,7 +384,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
error = PTR_ERR(file);
if (IS_ERR(file))
goto no_file;
ima_shm_check(file);
id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
if (id < 0) {
......@@ -891,7 +890,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations);
if (!file)
goto out_free;
ima_shm_check(file);
ima_counts_get(file);
file->private_data = sfd;
file->f_mapping = shp->shm_file->f_mapping;
......
......@@ -167,7 +167,7 @@ EXPORT_SYMBOL(prepare_creds);
/*
* Prepare credentials for current to perform an execve()
* - The caller must hold current->cred_exec_mutex
* - The caller must hold current->cred_guard_mutex
*/
struct cred *prepare_exec_creds(void)
{
......@@ -276,7 +276,7 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
struct cred *new;
int ret;
mutex_init(&p->cred_exec_mutex);
mutex_init(&p->cred_guard_mutex);
if (
#ifdef CONFIG_KEYS
......
......@@ -1472,6 +1472,7 @@ static int wait_consider_task(struct task_struct *parent, int ptrace,
*/
if (*notask_error)
*notask_error = ret;
return 0;
}
if (likely(!ptrace) && unlikely(p->ptrace)) {
......
......@@ -73,6 +73,9 @@ DEFINE_MUTEX(module_mutex);
EXPORT_SYMBOL_GPL(module_mutex);
static LIST_HEAD(modules);
/* Block module loading/unloading? */
int modules_disabled = 0;
/* Waiting for a module to finish initializing? */
static DECLARE_WAIT_QUEUE_HEAD(module_wq);
......@@ -778,7 +781,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
char name[MODULE_NAME_LEN];
int ret, forced = 0;
if (!capable(CAP_SYS_MODULE))
if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
......@@ -2338,7 +2341,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
int ret = 0;
/* Must have permission */
if (!capable(CAP_SYS_MODULE))
if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
/* Only one module load at a time, please */
......
......@@ -175,10 +175,11 @@ int ptrace_attach(struct task_struct *task)
if (same_thread_group(task, current))
goto out;
/* Protect exec's credential calculations against our interference;
* SUID, SGID and LSM creds get determined differently under ptrace.
/* Protect the target's credential calculations against our
* interference; SUID, SGID and LSM creds get determined differently
* under ptrace.
*/
retval = mutex_lock_interruptible(&task->cred_exec_mutex);
retval = mutex_lock_interruptible(&task->cred_guard_mutex);
if (retval < 0)
goto out;
......@@ -222,7 +223,7 @@ int ptrace_attach(struct task_struct *task)
bad:
write_unlock_irqrestore(&tasklist_lock, flags);
task_unlock(task);
mutex_unlock(&task->cred_exec_mutex);
mutex_unlock(&task->cred_guard_mutex);
out:
return retval;
}
......
......@@ -247,14 +247,19 @@ void flush_sigqueue(struct sigpending *queue)
/*
* Flush all pending signals for a task.
*/
void __flush_signals(struct task_struct *t)
{
clear_tsk_thread_flag(t, TIF_SIGPENDING);
flush_sigqueue(&t->pending);
flush_sigqueue(&t->signal->shared_pending);
}
void flush_signals(struct task_struct *t)
{
unsigned long flags;
spin_lock_irqsave(&t->sighand->siglock, flags);
clear_tsk_thread_flag(t, TIF_SIGPENDING);
flush_sigqueue(&t->pending);
flush_sigqueue(&t->signal->shared_pending);
__flush_signals(t);
spin_unlock_irqrestore(&t->sighand->siglock, flags);
}
......
......@@ -114,6 +114,7 @@ static int ngroups_max = NGROUPS_MAX;
#ifdef CONFIG_MODULES
extern char modprobe_path[];
extern int modules_disabled;
#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
......@@ -534,6 +535,17 @@ static struct ctl_table kern_table[] = {
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "modules_disabled",
.data = &modules_disabled,
.maxlen = sizeof(int),
.mode = 0644,
/* only handle a transition from default "0" to "1" */
.proc_handler = &proc_dointvec_minmax,
.extra1 = &one,
.extra2 = &one,
},
#endif
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
{
......@@ -1233,7 +1245,6 @@ static struct ctl_table vm_table[] = {
.strategy = &sysctl_jiffies,
},
#endif
#ifdef CONFIG_SECURITY
{
.ctl_name = CTL_UNNUMBERED,
.procname = "mmap_min_addr",
......@@ -1242,7 +1253,6 @@ static struct ctl_table vm_table[] = {
.mode = 0644,
.proc_handler = &proc_doulongvec_minmax,
},
#endif
#ifdef CONFIG_NUMA
{
.ctl_name = CTL_UNNUMBERED,
......
......@@ -226,6 +226,25 @@ config HAVE_MLOCKED_PAGE_BIT
config MMU_NOTIFIER