Merge branch 'stable-4.9' of git://git.infradead.org/users/pcmoore/selinux into next

This commit is contained in:
James Morris 2016-09-19 12:27:10 +10:00
Родитель e350e24694 9b6a9ecc2d
Коммит de2f4b3453
13 изменённых файлов: 211 добавлений и 65 удалений

Просмотреть файл

@ -103,6 +103,13 @@ retry:
goto retry;
}
error = security_inode_copy_up_xattr(name);
if (error < 0 && error != -EOPNOTSUPP)
break;
if (error == 1) {
error = 0;
continue; /* Discard */
}
error = vfs_setxattr(new, name, value, size, 0);
if (error)
break;
@ -246,6 +253,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
struct dentry *upper = NULL;
umode_t mode = stat->mode;
int err;
const struct cred *old_creds = NULL;
struct cred *new_creds = NULL;
newdentry = ovl_lookup_temp(workdir, dentry);
err = PTR_ERR(newdentry);
@ -258,10 +267,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
if (IS_ERR(upper))
goto out1;
err = security_inode_copy_up(dentry, &new_creds);
if (err < 0)
goto out2;
if (new_creds)
old_creds = override_creds(new_creds);
/* Can't properly set mode on creation because of the umask */
stat->mode &= S_IFMT;
err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
stat->mode = mode;
if (new_creds) {
revert_creds(old_creds);
put_cred(new_creds);
}
if (err)
goto out2;

Просмотреть файл

@ -435,6 +435,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
if (override_cred) {
override_cred->fsuid = inode->i_uid;
override_cred->fsgid = inode->i_gid;
if (!hardlink) {
err = security_dentry_create_files_as(dentry,
stat->mode, &dentry->d_name, old_cred,
override_cred);
if (err) {
put_cred(override_cred);
goto out_revert_creds;
}
}
put_cred(override_creds(override_cred));
put_cred(override_cred);
@ -445,6 +454,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
err = ovl_create_over_whiteout(dentry, inode, stat,
link, hardlink);
}
out_revert_creds:
revert_creds(old_cred);
if (!err) {
struct inode *realinode = d_inode(ovl_dentry_upper(dentry));

Просмотреть файл

@ -151,6 +151,16 @@
* @name name of the last path component used to create file
* @ctx pointer to place the pointer to the resulting context in.
* @ctxlen point to place the length of the resulting context.
* @dentry_create_files_as:
* Compute a context for a dentry as the inode is not yet available
* and set that context in passed in creds so that new files are
* created using that context. Context is calculated using the
* passed in creds and not the creds of the caller.
* @dentry dentry to use in calculating the context.
* @mode mode used to determine resource type.
* @name name of the last path component used to create file
* @old creds which should be used for context calculation
* @new creds to modify
*
*
* Security hooks for inode operations.
@ -401,6 +411,23 @@
* @inode contains a pointer to the inode.
* @secid contains a pointer to the location where result will be saved.
* In case of failure, @secid will be set to zero.
* @inode_copy_up:
* A file is about to be copied up from lower layer to upper layer of
* overlay filesystem. Security module can prepare a set of new creds
* and modify as need be and return new creds. Caller will switch to
* new creds temporarily to create new file and release newly allocated
* creds.
* @src indicates the union dentry of file that is being copied up.
* @new pointer to pointer to return newly allocated creds.
* Returns 0 on success or a negative error code on error.
* @inode_copy_up_xattr:
* Filter the xattrs being copied up when a unioned file is copied
* up from a lower layer to the union/overlay layer.
* @name indicates the name of the xattr.
* Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if
* security module does not know about attribute or a negative error code
* to abort the copy up. Note that the caller is responsible for reading
* and writing the xattrs as this hook is merely a filter.
*
* Security hooks for file operations
*
@ -1358,6 +1385,10 @@ union security_list_options {
int (*dentry_init_security)(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx,
u32 *ctxlen);
int (*dentry_create_files_as)(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old,
struct cred *new);
#ifdef CONFIG_SECURITY_PATH
@ -1425,6 +1456,8 @@ union security_list_options {
int (*inode_listsecurity)(struct inode *inode, char *buffer,
size_t buffer_size);
void (*inode_getsecid)(struct inode *inode, u32 *secid);
int (*inode_copy_up)(struct dentry *src, struct cred **new);
int (*inode_copy_up_xattr)(const char *name);
int (*file_permission)(struct file *file, int mask);
int (*file_alloc_security)(struct file *file);
@ -1655,6 +1688,7 @@ struct security_hook_heads {
struct list_head sb_clone_mnt_opts;
struct list_head sb_parse_opts_str;
struct list_head dentry_init_security;
struct list_head dentry_create_files_as;
#ifdef CONFIG_SECURITY_PATH
struct list_head path_unlink;
struct list_head path_mkdir;
@ -1695,6 +1729,8 @@ struct security_hook_heads {
struct list_head inode_setsecurity;
struct list_head inode_listsecurity;
struct list_head inode_getsecid;
struct list_head inode_copy_up;
struct list_head inode_copy_up_xattr;
struct list_head file_permission;
struct list_head file_alloc_security;
struct list_head file_free_security;

Просмотреть файл

@ -242,6 +242,10 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
int security_dentry_init_security(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx,
u32 *ctxlen);
int security_dentry_create_files_as(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old,
struct cred *new);
int security_inode_alloc(struct inode *inode);
void security_inode_free(struct inode *inode);
@ -282,6 +286,8 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
void security_inode_getsecid(struct inode *inode, u32 *secid);
int security_inode_copy_up(struct dentry *src, struct cred **new);
int security_inode_copy_up_xattr(const char *name);
int security_file_permission(struct file *file, int mask);
int security_file_alloc(struct file *file);
void security_file_free(struct file *file);
@ -597,6 +603,14 @@ static inline int security_dentry_init_security(struct dentry *dentry,
return -EOPNOTSUPP;
}
static inline int security_dentry_create_files_as(struct dentry *dentry,
int mode, struct qstr *name,
const struct cred *old,
struct cred *new)
{
return 0;
}
static inline int security_inode_init_security(struct inode *inode,
struct inode *dir,
@ -757,6 +771,16 @@ static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
*secid = 0;
}
static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
{
return 0;
}
static inline int security_inode_copy_up_xattr(const char *name)
{
return -EOPNOTSUPP;
}
static inline int security_file_permission(struct file *file, int mask)
{
return 0;

Просмотреть файл

@ -99,7 +99,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
}
return ret;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
/**
* ipv6_skb_to_auditdata : fill auditdata from skb
* @skb : the skb
@ -257,7 +257,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format(ab, " ino=%lu", inode->i_ino);
}
audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd);
audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
break;
}
case LSM_AUDIT_DATA_DENTRY: {

Просмотреть файл

@ -364,6 +364,15 @@ int security_dentry_init_security(struct dentry *dentry, int mode,
}
EXPORT_SYMBOL(security_dentry_init_security);
int security_dentry_create_files_as(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old, struct cred *new)
{
return call_int_hook(dentry_create_files_as, 0, dentry, mode,
name, old, new);
}
EXPORT_SYMBOL(security_dentry_create_files_as);
int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
@ -748,6 +757,18 @@ void security_inode_getsecid(struct inode *inode, u32 *secid)
call_void_hook(inode_getsecid, inode, secid);
}
int security_inode_copy_up(struct dentry *src, struct cred **new)
{
return call_int_hook(inode_copy_up, 0, src, new);
}
EXPORT_SYMBOL(security_inode_copy_up);
int security_inode_copy_up_xattr(const char *name)
{
return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name);
}
EXPORT_SYMBOL(security_inode_copy_up_xattr);
int security_file_permission(struct file *file, int mask)
{
int ret;
@ -1623,6 +1644,8 @@ struct security_hook_heads security_hook_heads = {
LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
.dentry_init_security =
LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
.dentry_create_files_as =
LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as),
#ifdef CONFIG_SECURITY_PATH
.path_unlink = LIST_HEAD_INIT(security_hook_heads.path_unlink),
.path_mkdir = LIST_HEAD_INIT(security_hook_heads.path_mkdir),
@ -1684,6 +1707,10 @@ struct security_hook_heads security_hook_heads = {
LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
.inode_getsecid =
LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
.inode_copy_up =
LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
.inode_copy_up_xattr =
LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr),
.file_permission =
LIST_HEAD_INIT(security_hook_heads.file_permission),
.file_alloc_security =

Просмотреть файл

@ -93,41 +93,3 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
via /selinux/checkreqprot if authorized by policy.
If you are unsure how to answer this question, answer 0.
config SECURITY_SELINUX_POLICYDB_VERSION_MAX
bool "NSA SELinux maximum supported policy format version"
depends on SECURITY_SELINUX
default n
help
This option enables the maximum policy format version supported
by SELinux to be set to a particular value. This value is reported
to userspace via /selinux/policyvers and used at policy load time.
It can be adjusted downward to support legacy userland (init) that
does not correctly handle kernels that support newer policy versions.
Examples:
For the Fedora Core 3 or 4 Linux distributions, enable this option
and set the value via the next option. For Fedora Core 5 and later,
do not enable this option.
If you are unsure how to answer this question, answer N.
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
int "NSA SELinux maximum supported policy format version value"
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
range 15 23
default 19
help
This option sets the value for the maximum policy format version
supported by SELinux.
Examples:
For Fedora Core 3, use 18.
For Fedora Core 4, use 19.
If you are unsure how to answer this question, look for the
policy format version supported by your policy toolchain, by
running 'checkpolicy -V'. Or look at what policy you have
installed under /etc/selinux/$SELINUXTYPE/policy, where
SELINUXTYPE is defined in your /etc/selinux/config.

Просмотреть файл

@ -1808,13 +1808,13 @@ out:
/*
* Determine the label for an inode that might be unioned.
*/
static int selinux_determine_inode_label(struct inode *dir,
const struct qstr *name,
u16 tclass,
u32 *_new_isid)
static int
selinux_determine_inode_label(const struct task_security_struct *tsec,
struct inode *dir,
const struct qstr *name, u16 tclass,
u32 *_new_isid)
{
const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
const struct task_security_struct *tsec = current_security();
if ((sbsec->flags & SE_SBINITIALIZED) &&
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
@ -1857,8 +1857,8 @@ static int may_create(struct inode *dir,
if (rc)
return rc;
rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
&newsid);
rc = selinux_determine_inode_label(current_security(), dir,
&dentry->d_name, tclass, &newsid);
if (rc)
return rc;
@ -2838,7 +2838,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
u32 newsid;
int rc;
rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
rc = selinux_determine_inode_label(current_security(),
d_inode(dentry->d_parent), name,
inode_mode_to_security_class(mode),
&newsid);
if (rc)
@ -2847,6 +2848,27 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
return security_sid_to_context(newsid, (char **)ctx, ctxlen);
}
static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old,
struct cred *new)
{
u32 newsid;
int rc;
struct task_security_struct *tsec;
rc = selinux_determine_inode_label(old->security,
d_inode(dentry->d_parent), name,
inode_mode_to_security_class(mode),
&newsid);
if (rc)
return rc;
tsec = new->security;
tsec->create_sid = newsid;
return 0;
}
static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const char **name,
@ -2863,7 +2885,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
sid = tsec->sid;
newsid = tsec->create_sid;
rc = selinux_determine_inode_label(
rc = selinux_determine_inode_label(current_security(),
dir, qstr,
inode_mode_to_security_class(inode->i_mode),
&newsid);
@ -3293,6 +3315,41 @@ static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
*secid = isec->sid;
}
static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
{
u32 sid;
struct task_security_struct *tsec;
struct cred *new_creds = *new;
if (new_creds == NULL) {
new_creds = prepare_creds();
if (!new_creds)
return -ENOMEM;
}
tsec = new_creds->security;
/* Get label from overlay inode and set it in create_sid */
selinux_inode_getsecid(d_inode(src), &sid);
tsec->create_sid = sid;
*new = new_creds;
return 0;
}
static int selinux_inode_copy_up_xattr(const char *name)
{
/* The copy_up hook above sets the initial context on an inode, but we
* don't then want to overwrite it by blindly copying all the lower
* xattrs up. Instead, we have to filter out SELinux-related xattrs.
*/
if (strcmp(name, XATTR_NAME_SELINUX) == 0)
return 1; /* Discard */
/*
* Any other attribute apart from SELINUX is not claimed, supported
* by selinux.
*/
return -EOPNOTSUPP;
}
/* file security operations */
static int selinux_revalidate_file_permission(struct file *file, int mask)
@ -3984,7 +4041,7 @@ out:
return ret;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv6(struct sk_buff *skb,
@ -4075,7 +4132,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
&ad->u.net->v4info.daddr);
goto okay;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6:
ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret)
@ -5029,7 +5086,7 @@ static unsigned int selinux_ipv4_forward(void *priv,
return selinux_ip_forward(skb, state->in, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int selinux_ipv6_forward(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
@ -5087,7 +5144,7 @@ static unsigned int selinux_ipv4_output(void *priv,
return selinux_ip_output(skb, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int selinux_ipv6_output(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
@ -5273,7 +5330,7 @@ static unsigned int selinux_ipv4_postroute(void *priv,
return selinux_ip_postroute(skb, state->out, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int selinux_ipv6_postroute(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
@ -6062,6 +6119,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
@ -6088,6 +6146,8 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
LSM_HOOK_INIT(file_permission, selinux_file_permission),
LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
@ -6317,7 +6377,7 @@ static struct nf_hook_ops selinux_nf_ops[] = {
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_SELINUX_FIRST,
},
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
{
.hook = selinux_ipv6_postroute,
.pf = NFPROTO_IPV6,

Просмотреть файл

@ -39,11 +39,7 @@
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_XPERMS_IOCTL
#endif
/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f

Просмотреть файл

@ -242,6 +242,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
goto err;
len = le32_to_cpu(buf[2]);
if (((len == 0) || (len == (u32)-1)))
goto err;
rc = -ENOMEM;
key = kmalloc(len + 1, GFP_KERNEL);

Просмотреть файл

@ -374,6 +374,9 @@ int ebitmap_read(struct ebitmap *e, void *fp)
goto ok;
}
if (e->highbit && !count)
goto bad;
for (i = 0; i < count; i++) {
rc = next_entry(&startbit, fp, sizeof(u32));
if (rc < 0) {

Просмотреть файл

@ -541,21 +541,21 @@ static int policydb_index(struct policydb *p)
rc = -ENOMEM;
p->class_val_to_struct =
kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)),
kzalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)),
GFP_KERNEL);
if (!p->class_val_to_struct)
goto out;
rc = -ENOMEM;
p->role_val_to_struct =
kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
kzalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
GFP_KERNEL);
if (!p->role_val_to_struct)
goto out;
rc = -ENOMEM;
p->user_val_to_struct =
kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
kzalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
GFP_KERNEL);
if (!p->user_val_to_struct)
goto out;
@ -964,7 +964,7 @@ int policydb_context_isvalid(struct policydb *p, struct context *c)
* Role must be authorized for the type.
*/
role = p->role_val_to_struct[c->role - 1];
if (!ebitmap_get_bit(&role->types, c->type - 1))
if (!role || !ebitmap_get_bit(&role->types, c->type - 1))
/* role may not be associated with type */
return 0;
@ -1094,6 +1094,9 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len)
int rc;
char *str;
if ((len == 0) || (len == (u32)-1))
return -EINVAL;
str = kmalloc(len + 1, flags);
if (!str)
return -ENOMEM;
@ -2414,6 +2417,7 @@ int policydb_read(struct policydb *p, void *fp)
} else
tr->tclass = p->process_class;
rc = -EINVAL;
if (!policydb_role_isvalid(p, tr->role) ||
!policydb_type_isvalid(p, tr->type) ||
!policydb_class_isvalid(p, tr->tclass) ||

Просмотреть файл

@ -20,7 +20,7 @@
#include <net/inet_sock.h>
#include "smack.h"
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int smack_ipv6_output(void *priv,
struct sk_buff *skb,
@ -64,7 +64,7 @@ static struct nf_hook_ops smack_nf_ops[] = {
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_SELINUX_FIRST,
},
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if IS_ENABLED(CONFIG_IPV6)
{
.hook = smack_ipv6_output,
.pf = NFPROTO_IPV6,