summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig1
-rw-r--r--security/apparmor/apparmorfs.c2
-rw-r--r--security/apparmor/file.c6
-rw-r--r--security/apparmor/lsm.c24
-rw-r--r--security/capability.c8
-rw-r--r--security/commoncap.c6
-rw-r--r--security/inode.c18
-rw-r--r--security/integrity/evm/evm_crypto.c4
-rw-r--r--security/integrity/evm/evm_main.c18
-rw-r--r--security/integrity/ima/ima_appraise.c10
-rw-r--r--security/keys/compat.c29
-rw-r--r--security/keys/internal.h5
-rw-r--r--security/keys/keyctl.c78
-rw-r--r--security/lsm_audit.c19
-rw-r--r--security/security.c59
-rw-r--r--security/selinux/avc.c6
-rw-r--r--security/selinux/hooks.c83
-rw-r--r--security/selinux/nlmsgtab.c13
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/avtab.c72
-rw-r--r--security/selinux/ss/avtab.h8
-rw-r--r--security/selinux/ss/mls.c10
-rw-r--r--security/selinux/ss/services.c6
-rw-r--r--security/smack/smack.h8
-rw-r--r--security/smack/smack_access.c43
-rw-r--r--security/smack/smack_lsm.c156
-rw-r--r--security/smack/smack_netfilter.c8
-rw-r--r--security/smack/smackfs.c99
-rw-r--r--security/tomoyo/.gitignore2
-rw-r--r--security/tomoyo/Kconfig1
-rw-r--r--security/tomoyo/Makefile55
-rw-r--r--security/tomoyo/common.h4
-rw-r--r--security/tomoyo/condition.c2
-rw-r--r--security/tomoyo/file.c4
-rw-r--r--security/tomoyo/policy/exception_policy.conf.default2
-rw-r--r--security/tomoyo/realpath.c16
-rw-r--r--security/tomoyo/tomoyo.c5
-rw-r--r--security/tomoyo/util.c13
-rw-r--r--security/yama/Kconfig2
-rw-r--r--security/yama/yama_lsm.c13
40 files changed, 537 insertions, 385 deletions
diff --git a/security/Kconfig b/security/Kconfig
index beb86b500adf..bf4ec46474b6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,7 @@ config SECURITY_DMESG_RESTRICT
config SECURITY
bool "Enable different security models"
depends on SYSFS
+ depends on MULTIUSER
help
This allows you to choose different security modules to be
configured into your kernel.
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 7db9954f1af2..ad4fa49ad1db 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -365,7 +365,7 @@ void __aa_fs_profile_rmdir(struct aa_profile *profile)
if (!profile->dents[i])
continue;
- r = profile->dents[i]->d_inode->i_private;
+ r = d_inode(profile->dents[i])->i_private;
securityfs_remove(profile->dents[i]);
aa_put_replacedby(r);
profile->dents[i] = NULL;
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index fdaa50cb1876..913f377a038a 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -259,7 +259,7 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
*/
static inline bool is_deleted(struct dentry *dentry)
{
- if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
+ if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
return 1;
return 0;
}
@@ -351,8 +351,8 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
struct path link = { new_dir->mnt, new_dentry };
struct path target = { new_dir->mnt, old_dentry };
struct path_cond cond = {
- old_dentry->d_inode->i_uid,
- old_dentry->d_inode->i_mode
+ d_backing_inode(old_dentry)->i_uid,
+ d_backing_inode(old_dentry)->i_mode
};
char *buffer = NULL, *buffer2 = NULL;
const char *lname, *tname = NULL, *info = NULL;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 107db88b1d5f..e5f1561439db 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -204,8 +204,8 @@ static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
struct dentry *dentry, u32 mask)
{
struct path path = { mnt, dentry };
- struct path_cond cond = { dentry->d_inode->i_uid,
- dentry->d_inode->i_mode
+ struct path_cond cond = { d_backing_inode(dentry)->i_uid,
+ d_backing_inode(dentry)->i_mode
};
return common_perm(op, &path, mask, &cond);
@@ -223,7 +223,7 @@ static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
static int common_perm_rm(int op, struct path *dir,
struct dentry *dentry, u32 mask)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct path_cond cond = { };
if (!inode || !dir->mnt || !mediated_filesystem(dentry))
@@ -281,8 +281,8 @@ static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
static int apparmor_path_truncate(struct path *path)
{
- struct path_cond cond = { path->dentry->d_inode->i_uid,
- path->dentry->d_inode->i_mode
+ struct path_cond cond = { d_backing_inode(path->dentry)->i_uid,
+ d_backing_inode(path->dentry)->i_mode
};
if (!path->mnt || !mediated_filesystem(path->dentry))
@@ -327,8 +327,8 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
if (!unconfined(profile)) {
struct path old_path = { old_dir->mnt, old_dentry };
struct path new_path = { new_dir->mnt, new_dentry };
- struct path_cond cond = { old_dentry->d_inode->i_uid,
- old_dentry->d_inode->i_mode
+ struct path_cond cond = { d_backing_inode(old_dentry)->i_uid,
+ d_backing_inode(old_dentry)->i_mode
};
error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0,
@@ -354,8 +354,8 @@ static int apparmor_path_chmod(struct path *path, umode_t mode)
static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
- struct path_cond cond = { path->dentry->d_inode->i_uid,
- path->dentry->d_inode->i_mode
+ struct path_cond cond = { d_backing_inode(path->dentry)->i_uid,
+ d_backing_inode(path->dentry)->i_mode
};
if (!mediated_filesystem(path->dentry))
@@ -364,12 +364,12 @@ static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
}
-static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int apparmor_inode_getattr(const struct path *path)
{
- if (!mediated_filesystem(dentry))
+ if (!mediated_filesystem(path->dentry))
return 0;
- return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
+ return common_perm_mnt_dentry(OP_GETATTR, path->mnt, path->dentry,
AA_MAY_META_READ);
}
diff --git a/security/capability.c b/security/capability.c
index 070dd46f62f4..0d03fcc489a4 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -225,7 +225,7 @@ static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
return 0;
}
-static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int cap_inode_getattr(const struct path *path)
{
return 0;
}
@@ -776,11 +776,6 @@ static int cap_tun_dev_open(void *security)
{
return 0;
}
-
-static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
-{
-}
-
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1134,7 +1129,6 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, tun_dev_open);
set_to_cap_if_null(ops, tun_dev_attach_queue);
set_to_cap_if_null(ops, tun_dev_attach);
- set_to_cap_if_null(ops, skb_owned_by);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
set_to_cap_if_null(ops, xfrm_policy_alloc_security);
diff --git a/security/commoncap.c b/security/commoncap.c
index f66713bd7450..f2875cd9f677 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -297,7 +297,7 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm)
*/
int cap_inode_need_killpriv(struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
int error;
if (!inode->i_op->getxattr)
@@ -319,7 +319,7 @@ int cap_inode_need_killpriv(struct dentry *dentry)
*/
int cap_inode_killpriv(struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
if (!inode->i_op->removexattr)
return 0;
@@ -375,7 +375,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
*/
int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
__u32 magic_etc;
unsigned tocopy, i;
int size;
diff --git a/security/inode.c b/security/inode.c
index 131a3c49f766..91503b79c5f8 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -27,7 +27,7 @@ static int mount_count;
static inline int positive(struct dentry *dentry)
{
- return dentry->d_inode && !d_unhashed(dentry);
+ return d_really_is_positive(dentry) && !d_unhashed(dentry);
}
static int fill_super(struct super_block *sb, void *data, int silent)
@@ -102,14 +102,14 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode,
if (!parent)
parent = mount->mnt_root;
- dir = parent->d_inode;
+ dir = d_inode(parent);
mutex_lock(&dir->i_mutex);
dentry = lookup_one_len(name, parent, strlen(name));
if (IS_ERR(dentry))
goto out;
- if (dentry->d_inode) {
+ if (d_really_is_positive(dentry)) {
error = -EEXIST;
goto out1;
}
@@ -197,20 +197,20 @@ void securityfs_remove(struct dentry *dentry)
return;
parent = dentry->d_parent;
- if (!parent || !parent->d_inode)
+ if (!parent || d_really_is_negative(parent))
return;
- mutex_lock(&parent->d_inode->i_mutex);
+ mutex_lock(&d_inode(parent)->i_mutex);
if (positive(dentry)) {
- if (dentry->d_inode) {
+ if (d_really_is_positive(dentry)) {
if (d_is_dir(dentry))
- simple_rmdir(parent->d_inode, dentry);
+ simple_rmdir(d_inode(parent), dentry);
else
- simple_unlink(parent->d_inode, dentry);
+ simple_unlink(d_inode(parent), dentry);
dput(dentry);
}
}
- mutex_unlock(&parent->d_inode->i_mutex);
+ mutex_unlock(&d_inode(parent)->i_mutex);
simple_release_fs(&mount, &mount_count);
}
EXPORT_SYMBOL_GPL(securityfs_remove);
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 5e9687f02e1b..159ef3ea4130 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -131,7 +131,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
size_t req_xattr_value_len,
char type, char *digest)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct shash_desc *desc;
char **xattrname;
size_t xattr_size = 0;
@@ -199,7 +199,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
const char *xattr_value, size_t xattr_value_len)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct evm_ima_xattr_data xattr_data;
int rc = 0;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index f589c9a05da2..10f994307a04 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -72,7 +72,7 @@ static void __init evm_init_config(void)
static int evm_find_protected_xattrs(struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
char **xattr;
int error;
int count = 0;
@@ -165,8 +165,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
/* Replace RSA with HMAC if not mounted readonly and
* not immutable
*/
- if (!IS_RDONLY(dentry->d_inode) &&
- !IS_IMMUTABLE(dentry->d_inode))
+ if (!IS_RDONLY(d_backing_inode(dentry)) &&
+ !IS_IMMUTABLE(d_backing_inode(dentry)))
evm_update_evmxattr(dentry, xattr_name,
xattr_value,
xattr_value_len);
@@ -235,7 +235,7 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry,
return INTEGRITY_UNKNOWN;
if (!iint) {
- iint = integrity_iint_find(dentry->d_inode);
+ iint = integrity_iint_find(d_backing_inode(dentry));
if (!iint)
return INTEGRITY_UNKNOWN;
}
@@ -253,7 +253,7 @@ EXPORT_SYMBOL_GPL(evm_verifyxattr);
*/
static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
return 0;
@@ -293,13 +293,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
if (evm_status == INTEGRITY_NOXATTRS) {
struct integrity_iint_cache *iint;
- iint = integrity_iint_find(dentry->d_inode);
+ iint = integrity_iint_find(d_backing_inode(dentry));
if (iint && (iint->flags & IMA_NEW_FILE))
return 0;
}
out:
if (evm_status != INTEGRITY_PASS)
- integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
+ integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
dentry->d_name.name, "appraise_metadata",
integrity_status_msg[evm_status],
-EPERM, 0);
@@ -379,7 +379,7 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
*/
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
if (!evm_initialized || !evm_protected_xattr(xattr_name))
return;
@@ -404,7 +404,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
if ((evm_status == INTEGRITY_PASS) ||
(evm_status == INTEGRITY_NOXATTRS))
return 0;
- integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
+ integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
dentry->d_name.name, "appraise_metadata",
integrity_status_msg[evm_status], -EPERM, 0);
return -EPERM;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index fffcdb0b31f0..4df493e4b3c9 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -165,7 +165,7 @@ void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
if (!inode->i_op->getxattr)
return 0;
@@ -190,7 +190,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
static const char op[] = "appraise_data";
char *cause = "unknown";
struct dentry *dentry = file->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
enum integrity_status status = INTEGRITY_UNKNOWN;
int rc = xattr_len, hash_start = 0;
@@ -314,7 +314,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
*/
void ima_inode_post_setattr(struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint;
int must_appraise, rc;
@@ -380,7 +380,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
if (result == 1) {
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
return -EINVAL;
- ima_reset_appraise_flags(dentry->d_inode,
+ ima_reset_appraise_flags(d_backing_inode(dentry),
(xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
result = 0;
}
@@ -393,7 +393,7 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
if (result == 1) {
- ima_reset_appraise_flags(dentry->d_inode, 0);
+ ima_reset_appraise_flags(d_backing_inode(dentry), 0);
result = 0;
}
return result;
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 347896548ad3..25430a3aa7f7 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov(
key_serial_t ringid)
{
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+ struct iov_iter from;
long ret;
- if (!_payload_iov || !ioc)
- goto no_payload;
+ if (!_payload_iov)
+ ioc = 0;
- ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
- ARRAY_SIZE(iovstack),
- iovstack, &iov);
+ ret = compat_import_iovec(WRITE, _payload_iov, ioc,
+ ARRAY_SIZE(iovstack), &iov,
+ &from);
if (ret < 0)
- goto err;
- if (ret == 0)
- goto no_payload_free;
-
- ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-err:
- if (iov != iovstack)
- kfree(iov);
- return ret;
+ return ret;
-no_payload_free:
- if (iov != iovstack)
- kfree(iov);
-no_payload:
- return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+ ret = keyctl_instantiate_key_common(id, &from, ringid);
+ kfree(iov);
+ return ret;
}
/*
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 200e37867336..5105c2c2da75 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
unsigned, key_serial_t);
extern long keyctl_invalidate_key(key_serial_t);
+struct iov_iter;
extern long keyctl_instantiate_key_common(key_serial_t,
- const struct iovec *,
- unsigned, size_t, key_serial_t);
+ struct iov_iter *,
+ key_serial_t);
#ifdef CONFIG_PERSISTENT_KEYRINGS
extern long keyctl_get_persistent(uid_t, key_serial_t);
extern unsigned persistent_keyring_expiry;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4743d71e4aa6..0b9ec78a7a7a 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -998,21 +998,6 @@ static int keyctl_change_reqkey_auth(struct key *key)
}
/*
- * Copy the iovec data from userspace
- */
-static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
- unsigned ioc)
-{
- for (; ioc > 0; ioc--) {
- if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0)
- return -EFAULT;
- buffer += iov->iov_len;
- iov++;
- }
- return 0;
-}
-
-/*
* Instantiate a key with the specified payload and link the key into the
* destination keyring if one is given.
*
@@ -1022,20 +1007,21 @@ static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
* If successful, 0 will be returned.
*/
long keyctl_instantiate_key_common(key_serial_t id,
- const struct iovec *payload_iov,
- unsigned ioc,
- size_t plen,
+ struct iov_iter *from,
key_serial_t ringid)
{
const struct cred *cred = current_cred();
struct request_key_auth *rka;
struct key *instkey, *dest_keyring;
+ size_t plen = from ? iov_iter_count(from) : 0;
void *payload;
long ret;
- bool vm = false;
kenter("%d,,%zu,%d", id, plen, ringid);
+ if (!plen)
+ from = NULL;
+
ret = -EINVAL;
if (plen > 1024 * 1024 - 1)
goto error;
@@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id,
/* pull the payload in if one was supplied */
payload = NULL;
- if (payload_iov) {
+ if (from) {
ret = -ENOMEM;
payload = kmalloc(plen, GFP_KERNEL);
if (!payload) {
if (plen <= PAGE_SIZE)
goto error;
- vm = true;
payload = vmalloc(plen);
if (!payload)
goto error;
}
- ret = copy_from_user_iovec(payload, payload_iov, ioc);
- if (ret < 0)
+ ret = -EFAULT;
+ if (copy_from_iter(payload, plen, from) != plen)
goto error2;
}
@@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
keyctl_change_reqkey_auth(NULL);
error2:
- if (!vm)
- kfree(payload);
- else
- vfree(payload);
+ kvfree(payload);
error:
return ret;
}
@@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id,
key_serial_t ringid)
{
if (_payload && plen) {
- struct iovec iov[1] = {
- [0].iov_base = (void __user *)_payload,
- [0].iov_len = plen
- };
+ struct iovec iov;
+ struct iov_iter from;
+ int ret;
- return keyctl_instantiate_key_common(id, iov, 1, plen, ringid);
+ ret = import_single_range(WRITE, (void __user *)_payload, plen,
+ &iov, &from);
+ if (unlikely(ret))
+ return ret;
+
+ return keyctl_instantiate_key_common(id, &from, ringid);
}
- return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+ return keyctl_instantiate_key_common(id, NULL, ringid);
}
/*
@@ -1138,29 +1124,19 @@ long keyctl_instantiate_key_iov(key_serial_t id,
key_serial_t ringid)
{
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+ struct iov_iter from;
long ret;
- if (!_payload_iov || !ioc)
- goto no_payload;
+ if (!_payload_iov)
+ ioc = 0;
- ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
- ARRAY_SIZE(iovstack), iovstack, &iov);
+ ret = import_iovec(WRITE, _payload_iov, ioc,
+ ARRAY_SIZE(iovstack), &iov, &from);
if (ret < 0)
- goto err;
- if (ret == 0)
- goto no_payload_free;
-
- ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-err:
- if (iov != iovstack)
- kfree(iov);
+ return ret;
+ ret = keyctl_instantiate_key_common(id, &from, ringid);
+ kfree(iov);
return ret;
-
-no_payload_free:
- if (iov != iovstack)
- kfree(iov);
-no_payload:
- return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
}
/*
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 69fdf3bc765b..1d34277dc402 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -211,7 +211,7 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
static void dump_common_audit_data(struct audit_buffer *ab,
struct common_audit_data *a)
{
- struct task_struct *tsk = current;
+ char comm[sizeof(current->comm)];
/*
* To keep stack sizes in check force programers to notice if they
@@ -220,8 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
*/
BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
- audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk));
- audit_log_untrustedstring(ab, tsk->comm);
+ audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
+ audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
switch (a->type) {
case LSM_AUDIT_DATA_NONE:
@@ -237,7 +237,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_d_path(ab, " path=", &a->u.path);
- inode = a->u.path.dentry->d_inode;
+ inode = d_backing_inode(a->u.path.dentry);
if (inode) {
audit_log_format(ab, " dev=");
audit_log_untrustedstring(ab, inode->i_sb->s_id);
@@ -251,7 +251,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
- inode = a->u.dentry->d_inode;
+ inode = d_backing_inode(a->u.dentry);
if (inode) {
audit_log_format(ab, " dev=");
audit_log_untrustedstring(ab, inode->i_sb->s_id);
@@ -276,16 +276,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format(ab, " ino=%lu", inode->i_ino);
break;
}
- case LSM_AUDIT_DATA_TASK:
- tsk = a->u.tsk;
+ case LSM_AUDIT_DATA_TASK: {
+ struct task_struct *tsk = a->u.tsk;
if (tsk) {
pid_t pid = task_pid_nr(tsk);
if (pid) {
+ char comm[sizeof(tsk->comm)];
audit_log_format(ab, " pid=%d comm=", pid);
- audit_log_untrustedstring(ab, tsk->comm);
+ audit_log_untrustedstring(ab,
+ memcpy(comm, tsk->comm, sizeof(comm)));
}
}
break;
+ }
case LSM_AUDIT_DATA_NET:
if (a->u.net->sk) {
struct sock *sk = a->u.net->sk;
diff --git a/security/security.c b/security/security.c
index e81d5bbe7363..8e9b1f4b9b45 100644
--- a/security/security.c
+++ b/security/security.c
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(security_old_inode_init_security);
int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
- if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
return security_ops->path_mknod(dir, dentry, mode, dev);
}
@@ -418,7 +418,7 @@ EXPORT_SYMBOL(security_path_mknod);
int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
- if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
return security_ops->path_mkdir(dir, dentry, mode);
}
@@ -426,14 +426,14 @@ EXPORT_SYMBOL(security_path_mkdir);
int security_path_rmdir(struct path *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
return security_ops->path_rmdir(dir, dentry);
}
int security_path_unlink(struct path *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
return security_ops->path_unlink(dir, dentry);
}
@@ -442,7 +442,7 @@ EXPORT_SYMBOL(security_path_unlink);
int security_path_symlink(struct path *dir, struct dentry *dentry,
const char *old_name)
{
- if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
return security_ops->path_symlink(dir, dentry, old_name);
}
@@ -450,7 +450,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry)
{
- if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
return 0;
return security_ops->path_link(old_dentry, new_dir, new_dentry);
}
@@ -459,8 +459,8 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
- if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
- (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
return 0;
if (flags & RENAME_EXCHANGE) {
@@ -477,21 +477,21 @@ EXPORT_SYMBOL(security_path_rename);
int security_path_truncate(struct path *path)
{
- if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
return security_ops->path_truncate(path);
}
int security_path_chmod(struct path *path, umode_t mode)
{
- if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
return security_ops->path_chmod(path, mode);
}
int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
- if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
return security_ops->path_chown(path, uid, gid);
}
@@ -513,14 +513,14 @@ EXPORT_SYMBOL_GPL(security_inode_create);
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
- if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
return 0;
return security_ops->inode_link(old_dentry, dir, new_dentry);
}
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_unlink(dir, dentry);
}
@@ -543,7 +543,7 @@ EXPORT_SYMBOL_GPL(security_inode_mkdir);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_rmdir(dir, dentry);
}
@@ -559,8 +559,8 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
- if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
- (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
return 0;
if (flags & RENAME_EXCHANGE) {
@@ -576,14 +576,14 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
int security_inode_readlink(struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_readlink(dentry);
}
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_follow_link(dentry, nd);
}
@@ -599,7 +599,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
int ret;
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
ret = security_ops->inode_setattr(dentry, attr);
if (ret)
@@ -608,11 +608,11 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
}
EXPORT_SYMBOL_GPL(security_inode_setattr);
-int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+int security_inode_getattr(const struct path *path)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
- return security_ops->inode_getattr(mnt, dentry);
+ return security_ops->inode_getattr(path);
}
int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -620,7 +620,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
{
int ret;
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
if (ret)
@@ -634,7 +634,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
void security_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return;
security_ops->inode_post_setxattr(dentry, name, value, size, flags);
evm_inode_post_setxattr(dentry, name, value, size);
@@ -642,14 +642,14 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
int security_inode_getxattr(struct dentry *dentry, const char *name)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_getxattr(dentry, name);
}
int security_inode_listxattr(struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
return security_ops->inode_listxattr(dentry);
}
@@ -658,7 +658,7 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
{
int ret;
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
ret = security_ops->inode_removexattr(dentry, name);
if (ret)
@@ -1359,11 +1359,6 @@ int security_tun_dev_open(void *security)
}
EXPORT_SYMBOL(security_tun_dev_open);
-void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
-{
- security_ops->skb_owned_by(skb, sk);
-}
-
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index afcc0aed9393..3c17dda9571d 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -724,12 +724,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
rcu_read_lock();
node = avc_lookup(ssid, tsid, tclass);
- if (unlikely(!node)) {
+ if (unlikely(!node))
node = avc_compute_av(ssid, tsid, tclass, avd);
- } else {
+ else
memcpy(avd, &node->ae.avd, sizeof(*avd));
- avd = &node->ae.avd;
- }
denied = requested & ~(avd->allowed);
if (unlikely(denied))
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4d1a54190388..7dade28affba 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -51,7 +51,6 @@
#include <linux/tty.h>
#include <net/icmp.h>
#include <net/ip.h> /* for local_port_range[] */
-#include <net/sock.h>
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/inet_connection_sock.h>
#include <net/net_namespace.h>
@@ -415,7 +414,7 @@ static int sb_finish_set_opts(struct super_block *sb)
{
struct superblock_security_struct *sbsec = sb->s_security;
struct dentry *root = sb->s_root;
- struct inode *root_inode = root->d_inode;
+ struct inode *root_inode = d_backing_inode(root);
int rc = 0;
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
@@ -553,7 +552,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
}
if (sbsec->flags & ROOTCONTEXT_MNT) {
- struct inode *root = sbsec->sb->s_root->d_inode;
+ struct inode *root = d_backing_inode(sbsec->sb->s_root);
struct inode_security_struct *isec = root->i_security;
rc = security_sid_to_context(isec->sid, &context, &len);
@@ -609,7 +608,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
int rc = 0, i;
struct superblock_security_struct *sbsec = sb->s_security;
const char *name = sb->s_type->name;
- struct inode *inode = sbsec->sb->s_root->d_inode;
+ struct inode *inode = d_backing_inode(sbsec->sb->s_root);
struct inode_security_struct *root_isec = inode->i_security;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
@@ -836,8 +835,8 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
goto mismatch;
if (oldflags & ROOTCONTEXT_MNT) {
- struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
- struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+ struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
+ struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
if (oldroot->sid != newroot->sid)
goto mismatch;
}
@@ -887,16 +886,16 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
if (!set_fscontext)
newsbsec->sid = sid;
if (!set_rootcontext) {
- struct inode *newinode = newsb->s_root->d_inode;
+ struct inode *newinode = d_backing_inode(newsb->s_root);
struct inode_security_struct *newisec = newinode->i_security;
newisec->sid = sid;
}
newsbsec->mntpoint_sid = sid;
}
if (set_rootcontext) {
- const struct inode *oldinode = oldsb->s_root->d_inode;
+ const struct inode *oldinode = d_backing_inode(oldsb->s_root);
const struct inode_security_struct *oldisec = oldinode->i_security;
- struct inode *newinode = newsb->s_root->d_inode;
+ struct inode *newinode = d_backing_inode(newsb->s_root);
struct inode_security_struct *newisec = newinode->i_security;
newisec->sid = oldisec->sid;
@@ -1611,7 +1610,7 @@ static inline int dentry_has_perm(const struct cred *cred,
struct dentry *dentry,
u32 av)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct common_audit_data ad;
ad.type = LSM_AUDIT_DATA_DENTRY;
@@ -1623,10 +1622,10 @@ static inline int dentry_has_perm(const struct cred *cred,
the path to help the auditing code to more easily generate the
pathname if needed. */
static inline int path_has_perm(const struct cred *cred,
- struct path *path,
+ const struct path *path,
u32 av)
{
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode = d_backing_inode(path->dentry);
struct common_audit_data ad;
ad.type = LSM_AUDIT_DATA_PATH;
@@ -1754,7 +1753,7 @@ static int may_link(struct inode *dir,
int rc;
dsec = dir->i_security;
- isec = dentry->d_inode->i_security;
+ isec = d_backing_inode(dentry)->i_security;
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
@@ -1798,7 +1797,7 @@ static inline int may_rename(struct inode *old_dir,
int rc;
old_dsec = old_dir->i_security;
- old_isec = old_dentry->d_inode->i_security;
+ old_isec = d_backing_inode(old_dentry)->i_security;
old_is_dir = d_is_dir(old_dentry);
new_dsec = new_dir->i_security;
@@ -1828,7 +1827,7 @@ static inline int may_rename(struct inode *old_dir,
if (rc)
return rc;
if (d_is_positive(new_dentry)) {
- new_isec = new_dentry->d_inode->i_security;
+ new_isec = d_backing_inode(new_dentry)->i_security;
new_is_dir = d_is_dir(new_dentry);
rc = avc_has_perm(sid, new_isec->sid,
new_isec->sclass,
@@ -1964,7 +1963,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
{
u32 sid = task_sid(to);
struct file_security_struct *fsec = file->f_security;
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = d_backing_inode(file->f_path.dentry);
struct inode_security_struct *isec = inode->i_security;
struct common_audit_data ad;
int rc;
@@ -2628,7 +2627,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
break;
case ROOTCONTEXT_MNT: {
struct inode_security_struct *root_isec;
- root_isec = sb->s_root->d_inode->i_security;
+ root_isec = d_backing_inode(sb->s_root)->i_security;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
goto out_bad_option;
@@ -2728,7 +2727,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
struct task_security_struct *tsec;
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
- struct inode *dir = dentry->d_parent->d_inode;
+ struct inode *dir = d_backing_inode(dentry->d_parent);
u32 newsid;
int rc;
@@ -2954,15 +2953,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
return dentry_has_perm(cred, dentry, av);
}
-static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int selinux_inode_getattr(const struct path *path)
{
- const struct cred *cred = current_cred();
- struct path path;
-
- path.dentry = dentry;
- path.mnt = mnt;
-
- return path_has_perm(cred, &path, FILE__GETATTR);
+ return path_has_perm(current_cred(), path, FILE__GETATTR);
}
static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
@@ -2989,7 +2982,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec;
struct common_audit_data ad;
@@ -3066,7 +3059,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
struct inode_security_struct *isec = inode->i_security;
u32 newsid;
int rc;
@@ -4652,11 +4645,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
}
-static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
-{
- skb_set_owner_w(skb, sk);
-}
-
static int selinux_secmark_relabel_packet(u32 sid)
{
const struct task_security_struct *__tsec;
@@ -4858,21 +4846,17 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb,
static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
- return selinux_ip_forward(skb, in, PF_INET);
+ return selinux_ip_forward(skb, state->in, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
- return selinux_ip_forward(skb, in, PF_INET6);
+ return selinux_ip_forward(skb, state->in, PF_INET6);
}
#endif /* IPV6 */
@@ -4920,9 +4904,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
return selinux_ip_output(skb, PF_INET);
}
@@ -5097,21 +5079,17 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,
static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
- return selinux_ip_postroute(skb, out, PF_INET);
+ return selinux_ip_postroute(skb, state->out, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
- return selinux_ip_postroute(skb, out, PF_INET6);
+ return selinux_ip_postroute(skb, state->out, PF_INET6);
}
#endif /* IPV6 */
@@ -6041,7 +6019,6 @@ static struct security_operations selinux_ops = {
.tun_dev_attach_queue = selinux_tun_dev_attach_queue,
.tun_dev_attach = selinux_tun_dev_attach,
.tun_dev_open = selinux_tun_dev_open,
- .skb_owned_by = selinux_skb_owned_by,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 2df7b900e259..2bbb41822d8e 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -73,6 +73,9 @@ static struct nlmsg_perm nlmsg_route_perms[] =
{ RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_NEWNSID, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+ { RTM_DELNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_GETNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ },
};
static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -100,6 +103,13 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] =
{ XFRM_MSG_FLUSHPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
{ XFRM_MSG_NEWAE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
{ XFRM_MSG_GETAE, NETLINK_XFRM_SOCKET__NLMSG_READ },
+ { XFRM_MSG_REPORT, NETLINK_XFRM_SOCKET__NLMSG_READ },
+ { XFRM_MSG_MIGRATE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+ { XFRM_MSG_NEWSADINFO, NETLINK_XFRM_SOCKET__NLMSG_READ },
+ { XFRM_MSG_GETSADINFO, NETLINK_XFRM_SOCKET__NLMSG_READ },
+ { XFRM_MSG_NEWSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+ { XFRM_MSG_GETSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_READ },
+ { XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ },
};
static struct nlmsg_perm nlmsg_audit_perms[] =
@@ -143,6 +153,8 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
switch (sclass) {
case SECCLASS_NETLINK_ROUTE_SOCKET:
+ /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */
+ BUILD_BUG_ON(RTM_MAX != (RTM_NEWNSID + 3));
err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
sizeof(nlmsg_route_perms));
break;
@@ -153,6 +165,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
break;
case SECCLASS_NETLINK_XFRM_SOCKET:
+ BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_MAPPING);
err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
sizeof(nlmsg_xfrm_perms));
break;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 1684bcc78b34..d2787cca1fcb 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -152,7 +152,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
goto out;
/* No partial writes. */
- length = EINVAL;
+ length = -EINVAL;
if (*ppos != 0)
goto out;
@@ -1737,7 +1737,7 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
inc_nlink(inode);
d_add(dentry, inode);
/* bump link count on parent directory, too */
- inc_nlink(dir->d_inode);
+ inc_nlink(d_inode(dir));
return dentry;
}
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a3dd9faa19c0..b64f2772b030 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -25,10 +25,43 @@
static struct kmem_cache *avtab_node_cachep;
-static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+/* Based on MurmurHash3, written by Austin Appleby and placed in the
+ * public domain.
+ */
+static inline int avtab_hash(struct avtab_key *keyp, u32 mask)
{
- return ((keyp->target_class + (keyp->target_type << 2) +
- (keyp->source_type << 9)) & mask);
+ static const u32 c1 = 0xcc9e2d51;
+ static const u32 c2 = 0x1b873593;
+ static const u32 r1 = 15;
+ static const u32 r2 = 13;
+ static const u32 m = 5;
+ static const u32 n = 0xe6546b64;
+
+ u32 hash = 0;
+
+#define mix(input) { \
+ u32 v = input; \
+ v *= c1; \
+ v = (v << r1) | (v >> (32 - r1)); \
+ v *= c2; \
+ hash ^= v; \
+ hash = (hash << r2) | (hash >> (32 - r2)); \
+ hash = hash * m + n; \
+}
+
+ mix(keyp->target_class);
+ mix(keyp->target_type);
+ mix(keyp->source_type);
+
+#undef mix
+
+ hash ^= hash >> 16;
+ hash *= 0x85ebca6b;
+ hash ^= hash >> 13;
+ hash *= 0xc2b2ae35;
+ hash ^= hash >> 16;
+
+ return hash & mask;
}
static struct avtab_node*
@@ -46,8 +79,12 @@ avtab_insert_node(struct avtab *h, int hvalue,
newnode->next = prev->next;
prev->next = newnode;
} else {
- newnode->next = h->htable[hvalue];
- h->htable[hvalue] = newnode;
+ newnode->next = flex_array_get_ptr(h->htable, hvalue);
+ if (flex_array_put_ptr(h->htable, hvalue, newnode,
+ GFP_KERNEL|__GFP_ZERO)) {
+ kmem_cache_free(avtab_node_cachep, newnode);
+ return NULL;
+ }
}
h->nel++;
@@ -64,7 +101,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
return -EINVAL;
hvalue = avtab_hash(key, h->mask);
- for (prev = NULL, cur = h->htable[hvalue];
+ for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
cur;
prev = cur, cur = cur->next) {
if (key->source_type == cur->key.source_type &&
@@ -104,7 +141,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
if (!h || !h->htable)
return NULL;
hvalue = avtab_hash(key, h->mask);
- for (prev = NULL, cur = h->htable[hvalue];
+ for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
cur;
prev = cur, cur = cur->next) {
if (key->source_type == cur->key.source_type &&
@@ -135,7 +172,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
return NULL;
hvalue = avtab_hash(key, h->mask);
- for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+ for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+ cur = cur->next) {
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
@@ -170,7 +208,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
return NULL;
hvalue = avtab_hash(key, h->mask);
- for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+ for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+ cur = cur->next) {
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
@@ -228,15 +267,14 @@ void avtab_destroy(struct avtab *h)
return;
for (i = 0; i < h->nslot; i++) {
- cur = h->htable[i];
+ cur = flex_array_get_ptr(h->htable, i);
while (cur) {
temp = cur;
cur = cur->next;
kmem_cache_free(avtab_node_cachep, temp);
}
- h->htable[i] = NULL;
}
- kfree(h->htable);
+ flex_array_free(h->htable);
h->htable = NULL;
h->nslot = 0;
h->mask = 0;
@@ -251,7 +289,7 @@ int avtab_init(struct avtab *h)
int avtab_alloc(struct avtab *h, u32 nrules)
{
- u16 mask = 0;
+ u32 mask = 0;
u32 shift = 0;
u32 work = nrules;
u32 nslot = 0;
@@ -270,7 +308,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
nslot = MAX_AVTAB_HASH_BUCKETS;
mask = nslot - 1;
- h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
+ h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot,
+ GFP_KERNEL | __GFP_ZERO);
if (!h->htable)
return -ENOMEM;
@@ -293,7 +332,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
max_chain_len = 0;
chain2_len_sum = 0;
for (i = 0; i < h->nslot; i++) {
- cur = h->htable[i];
+ cur = flex_array_get_ptr(h->htable, i);
if (cur) {
slots_used++;
chain_len = 0;
@@ -534,7 +573,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
return rc;
for (i = 0; i < a->nslot; i++) {
- for (cur = a->htable[i]; cur; cur = cur->next) {
+ for (cur = flex_array_get_ptr(a->htable, i); cur;
+ cur = cur->next) {
rc = avtab_write_item(p, cur, fp);
if (rc)
return rc;
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 63ce2f9e441d..adb451cd44f9 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -23,6 +23,8 @@
#ifndef _SS_AVTAB_H_
#define _SS_AVTAB_H_
+#include <linux/flex_array.h>
+
struct avtab_key {
u16 source_type; /* source type */
u16 target_type; /* target type */
@@ -51,10 +53,10 @@ struct avtab_node {
};
struct avtab {
- struct avtab_node **htable;
+ struct flex_array *htable;
u32 nel; /* number of elements */
u32 nslot; /* number of hash slots */
- u16 mask; /* mask to compute hash func */
+ u32 mask; /* mask to compute hash func */
};
@@ -84,7 +86,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified
void avtab_cache_init(void);
void avtab_cache_destroy(void);
-#define MAX_AVTAB_HASH_BITS 11
+#define MAX_AVTAB_HASH_BITS 16
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
#endif /* _SS_AVTAB_H_ */
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index d307b37ddc2b..e1088842232c 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -654,19 +654,15 @@ int mls_import_netlbl_cat(struct context *context,
rc = ebitmap_netlbl_import(&context->range.level[0].cat,
secattr->attr.mls.cat);
- if (rc != 0)
- goto import_netlbl_cat_failure;
-
- rc = ebitmap_cpy(&context->range.level[1].cat,
- &context->range.level[0].cat);
- if (rc != 0)
+ if (rc)
goto import_netlbl_cat_failure;
+ memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
+ sizeof(context->range.level[0].cat));
return 0;
import_netlbl_cat_failure:
ebitmap_destroy(&context->range.level[0].cat);
- ebitmap_destroy(&context->range.level[1].cat);
return rc;
}
#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index a1d3944751b9..9e2d82070915 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -3179,13 +3179,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
ctx_new.type = ctx->type;
mls_import_netlbl_lvl(&ctx_new, secattr);
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
- rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
- secattr->attr.mls.cat);
+ rc = mls_import_netlbl_cat(&ctx_new, secattr);
if (rc)
goto out;
- memcpy(&ctx_new.range.level[1].cat,
- &ctx_new.range.level[0].cat,
- sizeof(ctx_new.range.level[0].cat));
}
rc = -EIDRM;
if (!mls_context_isvalid(&policydb, &ctx_new))
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 67ccb7b2b89b..49eada6266ec 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -105,6 +105,7 @@ struct task_smack {
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
+#define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */
/*
* A label access rule.
@@ -193,6 +194,10 @@ struct smk_port_label {
#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
#define MAY_BRINGUP 0x00004000 /* Report use of this rule */
+#define SMACK_BRINGUP_ALLOW 1 /* Allow bringup mode */
+#define SMACK_UNCONFINED_SUBJECT 2 /* Allow unconfined label */
+#define SMACK_UNCONFINED_OBJECT 3 /* Allow unconfined label */
+
/*
* Just to make the common cases easier to deal with
*/
@@ -254,6 +259,9 @@ extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
extern struct smack_known *smack_onlycap;
extern struct smack_known *smack_syslog_label;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+extern struct smack_known *smack_unconfined;
+#endif
extern struct smack_known smack_cipso_option;
extern int smack_ptrace_rule;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 1158430f5bb9..0f410fc56e33 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
/*
* Hardcoded comparisons.
- *
+ */
+ /*
* A star subject can't access any object.
*/
if (subject == &smack_known_star) {
@@ -189,10 +190,20 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
* succeed because of "b" rules.
*/
if (may & MAY_BRINGUP)
- rc = MAY_BRINGUP;
+ rc = SMACK_BRINGUP_ALLOW;
#endif
out_audit:
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ if (rc < 0) {
+ if (object == smack_unconfined)
+ rc = SMACK_UNCONFINED_OBJECT;
+ if (subject == smack_unconfined)
+ rc = SMACK_UNCONFINED_SUBJECT;
+ }
+#endif
+
#ifdef CONFIG_AUDIT
if (a)
smack_log(subject->smk_known, object->smk_known,
@@ -338,19 +349,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
void smack_log(char *subject_label, char *object_label, int request,
int result, struct smk_audit_info *ad)
{
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
+#else
char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
+#endif
struct smack_audit_data *sad;
struct common_audit_data *a = &ad->a;
-#ifdef CONFIG_SECURITY_SMACK_BRINGUP
- /*
- * The result may be positive in bringup mode.
- */
- if (result > 0)
- result = 0;
-#endif
/* check if we have to log the current event */
- if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
+ if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
return;
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return;
@@ -364,6 +372,21 @@ void smack_log(char *subject_label, char *object_label, int request,
smack_str_from_perm(request_buffer, request);
sad->subject = subject_label;
sad->object = object_label;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ /*
+ * The result may be positive in bringup mode.
+ * A positive result is an allow, but not for normal reasons.
+ * Mark it as successful, but don't filter it out even if
+ * the logging policy says to do so.
+ */
+ if (result == SMACK_UNCONFINED_SUBJECT)
+ strcat(request_buffer, "(US)");
+ else if (result == SMACK_UNCONFINED_OBJECT)
+ strcat(request_buffer, "(UO)");
+
+ if (result > 0)
+ result = 0;
+#endif
sad->request = request_buffer;
sad->result = result;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c934311812f1..b644757886bc 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;
int smack_enabled;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static char *smk_bu_mess[] = {
+ "Bringup Error", /* Unused */
+ "Bringup", /* SMACK_BRINGUP_ALLOW */
+ "Unconfined Subject", /* SMACK_UNCONFINED_SUBJECT */
+ "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
+};
+
static void smk_bu_mode(int mode, char *s)
{
int i = 0;
@@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) %s\n",
+ pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
sskp->smk_known, oskp->smk_known, acc, note);
return 0;
}
@@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) %s %s\n",
+ pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, oskp->smk_known,
acc, current->comm, note);
return 0;
@@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
+ pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, smk_task->smk_known, acc,
current->comm, otp->comm);
return 0;
@@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
static int smk_bu_inode(struct inode *inode, int mode, int rc)
{
struct task_smack *tsp = current_security();
+ struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
+ if (isp->smk_flags & SMK_INODE_IMPURE)
+ pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ inode->i_sb->s_id, inode->i_ino, current->comm);
+
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
+ if (rc == SMACK_UNCONFINED_SUBJECT &&
+ (mode & (MAY_WRITE | MAY_APPEND)))
+ isp->smk_flags |= SMK_INODE_IMPURE;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n",
- tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc,
+
+ pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
+ tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, current->comm);
return 0;
}
@@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc)
struct task_smack *tsp = current_security();
struct smack_known *sskp = tsp->smk_task;
struct inode *inode = file_inode(file);
+ struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
+ if (isp->smk_flags & SMK_INODE_IMPURE)
+ pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ inode->i_sb->s_id, inode->i_ino, current->comm);
+
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
+ pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
@@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
struct task_smack *tsp = cred->security;
struct smack_known *sskp = tsp->smk_task;
struct inode *inode = file->f_inode;
+ struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
+ if (isp->smk_flags & SMK_INODE_IMPURE)
+ pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ inode->i_sb->s_id, inode->i_ino, current->comm);
+
if (rc <= 0)
return rc;
+ if (rc > SMACK_UNCONFINED_OBJECT)
+ rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
+ pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
@@ -555,7 +593,7 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
struct dentry *root = sb->s_root;
- struct inode *inode = root->d_inode;
+ struct inode *inode = d_backing_inode(root);
struct superblock_smack *sp = sb->s_security;
struct inode_smack *isp;
struct smack_known *skp;
@@ -851,15 +889,15 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
- isp = smk_of_inode(old_dentry->d_inode);
+ isp = smk_of_inode(d_backing_inode(old_dentry));
rc = smk_curacc(isp, MAY_WRITE, &ad);
- rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_WRITE, rc);
if (rc == 0 && d_is_positive(new_dentry)) {
- isp = smk_of_inode(new_dentry->d_inode);
+ isp = smk_of_inode(d_backing_inode(new_dentry));
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
rc = smk_curacc(isp, MAY_WRITE, &ad);
- rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_WRITE, rc);
}
return rc;
@@ -875,7 +913,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
*/
static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
{
- struct inode *ip = dentry->d_inode;
+ struct inode *ip = d_backing_inode(dentry);
struct smk_audit_info ad;
int rc;
@@ -918,8 +956,8 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
/*
* You need write access to the thing you're removing
*/
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+ rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
if (rc == 0) {
/*
* You also need write access to the containing directory
@@ -957,15 +995,15 @@ static int smack_inode_rename(struct inode *old_inode,
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
- isp = smk_of_inode(old_dentry->d_inode);
+ isp = smk_of_inode(d_backing_inode(old_dentry));
rc = smk_curacc(isp, MAY_READWRITE, &ad);
- rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc);
+ rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_READWRITE, rc);
if (rc == 0 && d_is_positive(new_dentry)) {
- isp = smk_of_inode(new_dentry->d_inode);
+ isp = smk_of_inode(d_backing_inode(new_dentry));
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
rc = smk_curacc(isp, MAY_READWRITE, &ad);
- rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc);
+ rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_READWRITE, rc);
}
return rc;
}
@@ -1022,8 +1060,8 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+ rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
return rc;
}
@@ -1034,19 +1072,16 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
*
* Returns 0 if access is permitted, an error code otherwise
*/
-static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int smack_inode_getattr(const struct path *path)
{
struct smk_audit_info ad;
- struct path path;
+ struct inode *inode = d_backing_inode(path->dentry);
int rc;
- path.dentry = dentry;
- path.mnt = mnt;
-
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, path);
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+ smk_ad_setfield_u_fs_path(&ad, *path);
+ rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad);
+ rc = smk_bu_inode(inode, MAY_READ, rc);
return rc;
}
@@ -1107,8 +1142,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
if (rc == 0) {
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+ rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
}
return rc;
@@ -1129,7 +1164,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct smack_known *skp;
- struct inode_smack *isp = dentry->d_inode->i_security;
+ struct inode_smack *isp = d_backing_inode(dentry)->i_security;
if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@ -1174,8 +1209,8 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_READ, &ad);
+ rc = smk_bu_inode(d_backing_inode(dentry), MAY_READ, rc);
return rc;
}
@@ -1211,12 +1246,12 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
- rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+ rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
if (rc != 0)
return rc;
- isp = dentry->d_inode->i_security;
+ isp = d_backing_inode(dentry)->i_security;
/*
* Don't do anything special for these.
* XATTR_NAME_SMACKIPIN
@@ -2452,7 +2487,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
static int smack_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
- if (family != PF_INET || sock->sk == NULL)
+ struct socket_smack *ssp;
+
+ if (sock->sk == NULL)
+ return 0;
+
+ /*
+ * Sockets created by kernel threads receive web label.
+ */
+ if (unlikely(current->flags & PF_KTHREAD)) {
+ ssp = sock->sk->sk_security;
+ ssp->smk_in = &smack_known_web;
+ ssp->smk_out = &smack_known_web;
+ }
+
+ if (family != PF_INET)
return 0;
/*
* Set the outbound netlbl.
@@ -3986,6 +4035,36 @@ static int smack_key_permission(key_ref_t key_ref,
rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
return rc;
}
+
+/*
+ * smack_key_getsecurity - Smack label tagging the key
+ * @key points to the key to be queried
+ * @_buffer points to a pointer that should be set to point to the
+ * resulting string (if no label or an error occurs).
+ * Return the length of the string (including terminating NUL) or -ve if
+ * an error.
+ * May also return 0 (and a NULL buffer pointer) if there is no label.
+ */
+static int smack_key_getsecurity(struct key *key, char **_buffer)
+{
+ struct smack_known *skp = key->security;
+ size_t length;
+ char *copy;
+
+ if (key->security == NULL) {
+ *_buffer = NULL;
+ return 0;
+ }
+
+ copy = kstrdup(skp->smk_known, GFP_KERNEL);
+ if (copy == NULL)
+ return -ENOMEM;
+ length = strlen(copy) + 1;
+
+ *_buffer = copy;
+ return length;
+}
+
#endif /* CONFIG_KEYS */
/*
@@ -4310,6 +4389,7 @@ struct security_operations smack_ops = {
.key_alloc = smack_key_alloc,
.key_free = smack_key_free,
.key_permission = smack_key_permission,
+ .key_getsecurity = smack_key_getsecurity,
#endif /* CONFIG_KEYS */
/* Audit hooks */
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index c952632afb0d..a455cfc9ec1f 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -23,9 +23,7 @@
static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
struct socket_smack *ssp;
struct smack_known *skp;
@@ -42,9 +40,7 @@ static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct nf_hook_state *state)
{
struct socket_smack *ssp;
struct smack_known *skp;
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index bce4e8f1b267..d9682985349e 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -54,6 +54,9 @@ enum smk_inos {
SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
SMK_SYSLOG = 20, /* change syslog label) */
SMK_PTRACE = 21, /* set ptrace rule */
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ SMK_UNCONFINED = 22, /* define an unconfined label */
+#endif
};
/*
@@ -61,7 +64,6 @@ enum smk_inos {
*/
static DEFINE_MUTEX(smack_cipso_lock);
static DEFINE_MUTEX(smack_ambient_lock);
-static DEFINE_MUTEX(smack_syslog_lock);
static DEFINE_MUTEX(smk_netlbladdr_lock);
/*
@@ -95,6 +97,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
*/
struct smack_known *smack_onlycap;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/*
+ * Allow one label to be unconfined. This is for
+ * debugging and application bring-up purposes only.
+ * It is bad and wrong, but everyone seems to expect
+ * to have it.
+ */
+struct smack_known *smack_unconfined;
+#endif
+
/*
* If this value is set restrict syslog use to the label specified.
* It can be reset via smackfs/syslog
@@ -1717,6 +1729,85 @@ static const struct file_operations smk_onlycap_ops = {
.llseek = default_llseek,
};
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/**
+ * smk_read_unconfined - read() for smackfs/unconfined
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
+ size_t cn, loff_t *ppos)
+{
+ char *smack = "";
+ ssize_t rc = -EINVAL;
+ int asize;
+
+ if (*ppos != 0)
+ return 0;
+
+ if (smack_unconfined != NULL)
+ smack = smack_unconfined->smk_known;
+
+ asize = strlen(smack) + 1;
+
+ if (cn >= asize)
+ rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
+
+ return rc;
+}
+
+/**
+ * smk_write_unconfined - write() for smackfs/unconfined
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *data;
+ int rc = count;
+
+ if (!smack_privileged(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ data = kzalloc(count + 1, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ /*
+ * Should the null string be passed in unset the unconfined value.
+ * This seems like something to be careful with as usually
+ * smk_import only expects to return NULL for errors. It
+ * is usually the case that a nullstring or "\n" would be
+ * bad to pass to smk_import but in fact this is useful here.
+ *
+ * smk_import will also reject a label beginning with '-',
+ * so "-confine" will also work.
+ */
+ if (copy_from_user(data, buf, count) != 0)
+ rc = -EFAULT;
+ else
+ smack_unconfined = smk_import_entry(data, count);
+
+ kfree(data);
+ return rc;
+}
+
+static const struct file_operations smk_unconfined_ops = {
+ .read = smk_read_unconfined,
+ .write = smk_write_unconfined,
+ .llseek = default_llseek,
+};
+#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
+
/**
* smk_read_logging - read() for /smack/logging
* @filp: file pointer, not actually used
@@ -2384,6 +2475,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
"syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
[SMK_PTRACE] = {
"ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ [SMK_UNCONFINED] = {
+ "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
+#endif
/* last one */
{""}
};
@@ -2395,7 +2490,7 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
return rc;
}
- root_inode = sb->s_root->d_inode;
+ root_inode = d_inode(sb->s_root);
return 0;
}
diff --git a/security/tomoyo/.gitignore b/security/tomoyo/.gitignore
index 5caf1a6f5907..dc0f220a210b 100644
--- a/security/tomoyo/.gitignore
+++ b/security/tomoyo/.gitignore
@@ -1,2 +1,2 @@
builtin-policy.h
-policy/
+policy/*.conf
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
index 604e718d68d3..404dce66952a 100644
--- a/security/tomoyo/Kconfig
+++ b/security/tomoyo/Kconfig
@@ -6,6 +6,7 @@ config SECURITY_TOMOYO
select SECURITY_PATH
select SECURITY_NETWORK
select SRCU
+ select BUILD_BIN2C
default n
help
This selects TOMOYO Linux, pathname-based access control.
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 56a0c7be409e..65dbcb2fd850 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1,48 +1,15 @@
obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
-$(obj)/policy/profile.conf:
- @mkdir -p $(obj)/policy/
- @echo Creating an empty policy/profile.conf
- @touch $@
-
-$(obj)/policy/exception_policy.conf:
- @mkdir -p $(obj)/policy/
- @echo Creating a default policy/exception_policy.conf
- @echo initialize_domain /sbin/modprobe from any >> $@
- @echo initialize_domain /sbin/hotplug from any >> $@
-
-$(obj)/policy/domain_policy.conf:
- @mkdir -p $(obj)/policy/
- @echo Creating an empty policy/domain_policy.conf
- @touch $@
-
-$(obj)/policy/manager.conf:
- @mkdir -p $(obj)/policy/
- @echo Creating an empty policy/manager.conf
- @touch $@
-
-$(obj)/policy/stat.conf:
- @mkdir -p $(obj)/policy/
- @echo Creating an empty policy/stat.conf
- @touch $@
-
-$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
- @echo Generating built-in policy for TOMOYO 2.5.x.
- @echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp
- @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
- @echo "\"\";" >> $@.tmp
- @echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp
- @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
- @echo "\"\";" >> $@.tmp
- @echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp
- @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
- @echo "\"\";" >> $@.tmp
- @echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp
- @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
- @echo "\"\";" >> $@.tmp
- @echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp
- @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
- @echo "\"\";" >> $@.tmp
- @mv $@.tmp $@
+targets += builtin-policy.h
+define do_policy
+echo "static char tomoyo_builtin_$(1)[] __initdata ="; \
+$(objtree)/scripts/basic/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \
+echo ";"
+endef
+quiet_cmd_policy = POLICY $@
+ cmd_policy = ($(call do_policy,profile); $(call do_policy,exception_policy); $(call do_policy,domain_policy); $(call do_policy,manager); $(call do_policy,stat)) >$@
+
+$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(src)/policy/*.conf.default) FORCE
+ $(call if_changed,policy)
$(obj)/common.o: $(obj)/builtin-policy.h
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index b897d4862016..f9c9fb1d56b4 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -945,7 +945,7 @@ char *tomoyo_encode2(const char *str, int str_len);
char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
va_list args);
char *tomoyo_read_token(struct tomoyo_acl_param *param);
-char *tomoyo_realpath_from_path(struct path *path);
+char *tomoyo_realpath_from_path(const struct path *path);
char *tomoyo_realpath_nofollow(const char *pathname);
const char *tomoyo_get_exe(void);
const char *tomoyo_yesno(const unsigned int value);
@@ -978,7 +978,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
struct path *path2);
int tomoyo_path_number_perm(const u8 operation, struct path *path,
unsigned long number);
-int tomoyo_path_perm(const u8 operation, struct path *path,
+int tomoyo_path_perm(const u8 operation, const struct path *path,
const char *target);
unsigned int tomoyo_poll_control(struct file *file, poll_table *wait);
unsigned int tomoyo_poll_log(struct file *file, poll_table *wait);
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c
index 63681e8be628..6c4528d4b48f 100644
--- a/security/tomoyo/condition.c
+++ b/security/tomoyo/condition.c
@@ -714,7 +714,7 @@ void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
dentry = dget_parent(dentry);
break;
}
- inode = dentry->d_inode;
+ inode = d_backing_inode(dentry);
if (inode) {
struct tomoyo_mini_stat *stat = &obj->stat[i];
stat->uid = inode->i_uid;
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index c151a1869597..2367b100cc62 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -145,7 +145,7 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf)
*
* Returns true on success, false otherwise.
*/
-static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
+static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
{
buf->name = tomoyo_realpath_from_path(path);
if (buf->name) {
@@ -782,7 +782,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
*
* Returns 0 on success, negative value otherwise.
*/
-int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
+int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
{
struct tomoyo_request_info r;
struct tomoyo_obj_info obj = {
diff --git a/security/tomoyo/policy/exception_policy.conf.default b/security/tomoyo/policy/exception_policy.conf.default
new file mode 100644
index 000000000000..2678df4964ee
--- /dev/null
+++ b/security/tomoyo/policy/exception_policy.conf.default
@@ -0,0 +1,2 @@
+initialize_domain /sbin/modprobe from any
+initialize_domain /sbin/hotplug from any
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index bed745c8b1a3..5077f1968841 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -89,7 +89,7 @@ char *tomoyo_encode(const char *str)
*
* If dentry is a directory, trailing '/' is appended.
*/
-static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
+static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer,
const int buflen)
{
char *pos = ERR_PTR(-ENOMEM);
@@ -97,7 +97,7 @@ static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
/* go to whatever namespace root we are under */
pos = d_absolute_path(path, buffer, buflen - 1);
if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode = d_backing_inode(path->dentry);
if (inode && S_ISDIR(inode->i_mode)) {
buffer[buflen - 2] = '/';
buffer[buflen - 1] = '\0';
@@ -125,7 +125,7 @@ static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
if (buflen >= 256) {
pos = dentry_path_raw(dentry, buffer, buflen - 1);
if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = d_backing_inode(dentry);
if (inode && S_ISDIR(inode->i_mode)) {
buffer[buflen - 2] = '/';
buffer[buflen - 1] = '\0';
@@ -168,7 +168,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
if (!MAJOR(sb->s_dev))
goto prepend_filesystem_name;
{
- struct inode *inode = sb->s_root->d_inode;
+ struct inode *inode = d_backing_inode(sb->s_root);
/*
* Use filesystem name if filesystem does not support rename()
* operation.
@@ -216,10 +216,10 @@ out:
*
* Returns the buffer.
*/
-static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
+static char *tomoyo_get_socket_name(const struct path *path, char * const buffer,
const int buflen)
{
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode = d_backing_inode(path->dentry);
struct socket *sock = inode ? SOCKET_I(inode) : NULL;
struct sock *sk = sock ? sock->sk : NULL;
if (sk) {
@@ -247,7 +247,7 @@ static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
* These functions use kzalloc(), so the caller must call kfree()
* if these functions didn't return NULL.
*/
-char *tomoyo_realpath_from_path(struct path *path)
+char *tomoyo_realpath_from_path(const struct path *path)
{
char *buf = NULL;
char *name = NULL;
@@ -277,7 +277,7 @@ char *tomoyo_realpath_from_path(struct path *path)
pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
goto encode;
}
- inode = sb->s_root->d_inode;
+ inode = d_backing_inode(sb->s_root);
/*
* Get local name for filesystems without rename() operation
* or dentry without vfsmount.
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index f0b756e27fed..57c88d52ffa5 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -144,10 +144,9 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
*
* Returns 0 on success, negative value otherwise.
*/
-static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int tomoyo_inode_getattr(const struct path *path)
{
- struct path path = { mnt, dentry };
- return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL);
+ return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL);
}
/**
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 2952ba576fb9..b974a6997d7f 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -948,15 +948,18 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
*/
const char *tomoyo_get_exe(void)
{
+ struct file *exe_file;
+ const char *cp;
struct mm_struct *mm = current->mm;
- const char *cp = NULL;
if (!mm)
return NULL;
- down_read(&mm->mmap_sem);
- if (mm->exe_file)
- cp = tomoyo_realpath_from_path(&mm->exe_file->f_path);
- up_read(&mm->mmap_sem);
+ exe_file = get_mm_exe_file(mm);
+ if (!exe_file)
+ return NULL;
+
+ cp = tomoyo_realpath_from_path(&exe_file->f_path);
+ fput(exe_file);
return cp;
}
diff --git a/security/yama/Kconfig b/security/yama/Kconfig
index 20ef5143c0c0..3123e1da2fed 100644
--- a/security/yama/Kconfig
+++ b/security/yama/Kconfig
@@ -1,8 +1,6 @@
config SECURITY_YAMA
bool "Yama support"
depends on SECURITY
- select SECURITYFS
- select SECURITY_PATH
default n
help
This selects Yama, which extends DAC support with additional
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 13c88fbcf037..24aae2ae2b30 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -379,20 +379,17 @@ static struct security_operations yama_ops = {
static int yama_dointvec_minmax(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int rc;
+ struct ctl_table table_copy;
if (write && !capable(CAP_SYS_PTRACE))
return -EPERM;
- rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
- if (rc)
- return rc;
-
/* Lock the max value if it ever gets set. */
- if (write && *(int *)table->data == *(int *)table->extra2)
- table->extra1 = table->extra2;
+ table_copy = *table;
+ if (*(int *)table_copy.data == *(int *)table_copy.extra2)
+ table_copy.extra1 = table_copy.extra2;
- return rc;
+ return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos);
}
static int zero;