Merge da380aefdd ("Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs") into android-mainline
Steps on the way to 6.1-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id38fb40e845e349508d14972d82d63977fa3ad69
This commit is contained in:
+2
-1
@@ -841,7 +841,7 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
|
||||
};
|
||||
struct iov_iter iter;
|
||||
struct file *file = cprm->file;
|
||||
loff_t pos = file->f_pos;
|
||||
loff_t pos;
|
||||
ssize_t n;
|
||||
|
||||
if (cprm->to_skip) {
|
||||
@@ -853,6 +853,7 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
|
||||
return 0;
|
||||
if (dump_interrupted())
|
||||
return 0;
|
||||
pos = file->f_pos;
|
||||
iov_iter_bvec(&iter, WRITE, &bvec, 1, PAGE_SIZE);
|
||||
n = __kernel_write_iter(cprm->file, &iter, &pos);
|
||||
if (n != PAGE_SIZE)
|
||||
|
||||
+2
-2
@@ -991,7 +991,7 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *new,
|
||||
int fd;
|
||||
|
||||
fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, new,
|
||||
O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS), inode);
|
||||
O_RDONLY | (new->flags & UFFD_SHARED_FCNTL_FLAGS), inode);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@@ -2094,7 +2094,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
|
||||
mmgrab(ctx->mm);
|
||||
|
||||
fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, ctx,
|
||||
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS), NULL);
|
||||
O_RDONLY | (flags & UFFD_SHARED_FCNTL_FLAGS), NULL);
|
||||
if (fd < 0) {
|
||||
mmdrop(ctx->mm);
|
||||
kmem_cache_free(userfaultfd_ctx_cachep, ctx);
|
||||
|
||||
@@ -224,6 +224,7 @@ LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2,
|
||||
unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||
LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p,
|
||||
struct inode *inode)
|
||||
LSM_HOOK(int, 0, userns_create, const struct cred *cred)
|
||||
LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag)
|
||||
LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp,
|
||||
u32 *secid)
|
||||
|
||||
@@ -806,6 +806,10 @@
|
||||
* security attributes, e.g. for /proc/pid inodes.
|
||||
* @p contains the task_struct for the task.
|
||||
* @inode contains the inode structure for the inode.
|
||||
* @userns_create:
|
||||
* Check permission prior to creating a new user namespace.
|
||||
* @cred points to prepared creds.
|
||||
* Return 0 if successful, otherwise < 0 error code.
|
||||
*
|
||||
* Security hooks for Netlink messaging.
|
||||
*
|
||||
|
||||
@@ -437,6 +437,7 @@ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info,
|
||||
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5);
|
||||
void security_task_to_inode(struct task_struct *p, struct inode *inode);
|
||||
int security_create_user_ns(const struct cred *cred);
|
||||
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
|
||||
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
|
||||
int security_msg_msg_alloc(struct msg_msg *msg);
|
||||
@@ -1194,6 +1195,11 @@ static inline int security_task_prctl(int option, unsigned long arg2,
|
||||
static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
|
||||
{ }
|
||||
|
||||
static inline int security_create_user_ns(const struct cred *cred)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_ipc_permission(struct kern_ipc_perm *ipcp,
|
||||
short flag)
|
||||
{
|
||||
|
||||
@@ -335,6 +335,7 @@ BTF_ID(func, bpf_lsm_task_getsecid_obj)
|
||||
BTF_ID(func, bpf_lsm_task_prctl)
|
||||
BTF_ID(func, bpf_lsm_task_setscheduler)
|
||||
BTF_ID(func, bpf_lsm_task_to_inode)
|
||||
BTF_ID(func, bpf_lsm_userns_create)
|
||||
BTF_SET_END(sleepable_lsm_hooks)
|
||||
|
||||
bool bpf_lsm_is_sleepable_hook(u32 btf_id)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/securebits.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <keys/user-type.h>
|
||||
@@ -113,6 +114,10 @@ int create_user_ns(struct cred *new)
|
||||
!kgid_has_mapping(parent_ns, group))
|
||||
goto fail_dec;
|
||||
|
||||
ret = security_create_user_ns(new);
|
||||
if (ret < 0)
|
||||
goto fail_dec;
|
||||
|
||||
ret = -ENOMEM;
|
||||
ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL);
|
||||
if (!ns)
|
||||
|
||||
@@ -31,8 +31,7 @@ fi
|
||||
if selinuxenabled; then
|
||||
echo "SELinux is already enabled"
|
||||
echo "This prevents safely relabeling all files."
|
||||
echo "Boot with selinux=0 on the kernel command-line or"
|
||||
echo "SELINUX=disabled in /etc/selinux/config."
|
||||
echo "Boot with selinux=0 on the kernel command-line."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -78,7 +77,7 @@ cd /etc/selinux/dummy/contexts/files
|
||||
$SF -F file_contexts /
|
||||
|
||||
mounts=`cat /proc/$$/mounts | \
|
||||
egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
|
||||
grep -E "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
|
||||
awk '{ print $2 '}`
|
||||
$SF -F file_contexts $mounts
|
||||
|
||||
|
||||
@@ -750,22 +750,26 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
|
||||
const struct evm_ima_xattr_data *xvalue = xattr_value;
|
||||
int digsig = 0;
|
||||
int result;
|
||||
int err;
|
||||
|
||||
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
|
||||
xattr_value_len);
|
||||
if (result == 1) {
|
||||
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
|
||||
return -EINVAL;
|
||||
|
||||
err = validate_hash_algo(dentry, xvalue, xattr_value_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
|
||||
} else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) {
|
||||
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
|
||||
}
|
||||
if (result == 1 || evm_revalidate_status(xattr_name)) {
|
||||
result = validate_hash_algo(dentry, xvalue, xattr_value_len);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
|
||||
if (result == 1)
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ static const struct dmi_system_id uefi_skip_cert[] = {
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacMini8,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "Macmini8,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },
|
||||
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },
|
||||
|
||||
@@ -63,7 +63,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
|
||||
|
||||
if (kernel_locked_down >= what) {
|
||||
if (lockdown_reasons[what])
|
||||
pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
|
||||
pr_notice_ratelimited("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
|
||||
current->comm, lockdown_reasons[what]);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
+1
-13
@@ -44,9 +44,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||
struct iphdr *ih;
|
||||
|
||||
ih = ip_hdr(skb);
|
||||
if (ih == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
ad->u.net->v4info.saddr = ih->saddr;
|
||||
ad->u.net->v4info.daddr = ih->daddr;
|
||||
|
||||
@@ -59,8 +56,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||
switch (ih->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr *th = tcp_hdr(skb);
|
||||
if (th == NULL)
|
||||
break;
|
||||
|
||||
ad->u.net->sport = th->source;
|
||||
ad->u.net->dport = th->dest;
|
||||
@@ -68,8 +63,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
if (uh == NULL)
|
||||
break;
|
||||
|
||||
ad->u.net->sport = uh->source;
|
||||
ad->u.net->dport = uh->dest;
|
||||
@@ -77,8 +70,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||
}
|
||||
case IPPROTO_DCCP: {
|
||||
struct dccp_hdr *dh = dccp_hdr(skb);
|
||||
if (dh == NULL)
|
||||
break;
|
||||
|
||||
ad->u.net->sport = dh->dccph_sport;
|
||||
ad->u.net->dport = dh->dccph_dport;
|
||||
@@ -86,8 +77,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||
}
|
||||
case IPPROTO_SCTP: {
|
||||
struct sctphdr *sh = sctp_hdr(skb);
|
||||
if (sh == NULL)
|
||||
break;
|
||||
|
||||
ad->u.net->sport = sh->source;
|
||||
ad->u.net->dport = sh->dest;
|
||||
break;
|
||||
@@ -115,8 +105,6 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
||||
__be16 frag_off;
|
||||
|
||||
ip6 = ipv6_hdr(skb);
|
||||
if (ip6 == NULL)
|
||||
return -EINVAL;
|
||||
ad->u.net->v6info.saddr = ip6->saddr;
|
||||
ad->u.net->v6info.daddr = ip6->daddr;
|
||||
/* IPv6 can have several extension header before the Transport header
|
||||
|
||||
@@ -1909,6 +1909,11 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode)
|
||||
call_void_hook(task_to_inode, p, inode);
|
||||
}
|
||||
|
||||
int security_create_user_ns(const struct cred *cred)
|
||||
{
|
||||
return call_int_hook(userns_create, 0, cred);
|
||||
}
|
||||
|
||||
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
|
||||
{
|
||||
return call_int_hook(ipc_permission, 0, ipcp, flag);
|
||||
|
||||
+18
-15
@@ -4222,6 +4222,14 @@ static void selinux_task_to_inode(struct task_struct *p,
|
||||
spin_unlock(&isec->lock);
|
||||
}
|
||||
|
||||
static int selinux_userns_create(const struct cred *cred)
|
||||
{
|
||||
u32 sid = current_sid();
|
||||
|
||||
return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE,
|
||||
USER_NAMESPACE__CREATE, NULL);
|
||||
}
|
||||
|
||||
/* Returns error only if unable to parse addresses */
|
||||
static int selinux_parse_skb_ipv4(struct sk_buff *skb,
|
||||
struct common_audit_data *ad, u8 *proto)
|
||||
@@ -5987,7 +5995,6 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
isec = selinux_ipc(msq);
|
||||
ipc_init_security(isec, SECCLASS_MSGQ);
|
||||
@@ -5995,10 +6002,9 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
|
||||
ad.type = LSM_AUDIT_DATA_IPC;
|
||||
ad.u.ipc_id = msq->key;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_MSGQ,
|
||||
MSGQ__CREATE, &ad);
|
||||
return rc;
|
||||
return avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_MSGQ,
|
||||
MSGQ__CREATE, &ad);
|
||||
}
|
||||
|
||||
static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
|
||||
@@ -6126,7 +6132,6 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
isec = selinux_ipc(shp);
|
||||
ipc_init_security(isec, SECCLASS_SHM);
|
||||
@@ -6134,10 +6139,9 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
|
||||
ad.type = LSM_AUDIT_DATA_IPC;
|
||||
ad.u.ipc_id = shp->key;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_SHM,
|
||||
SHM__CREATE, &ad);
|
||||
return rc;
|
||||
return avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_SHM,
|
||||
SHM__CREATE, &ad);
|
||||
}
|
||||
|
||||
static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
|
||||
@@ -6211,7 +6215,6 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
isec = selinux_ipc(sma);
|
||||
ipc_init_security(isec, SECCLASS_SEM);
|
||||
@@ -6219,10 +6222,9 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
|
||||
ad.type = LSM_AUDIT_DATA_IPC;
|
||||
ad.u.ipc_id = sma->key;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_SEM,
|
||||
SEM__CREATE, &ad);
|
||||
return rc;
|
||||
return avc_has_perm(&selinux_state,
|
||||
sid, isec->sid, SECCLASS_SEM,
|
||||
SEM__CREATE, &ad);
|
||||
}
|
||||
|
||||
static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
|
||||
@@ -7134,6 +7136,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
||||
LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
|
||||
LSM_HOOK_INIT(task_kill, selinux_task_kill),
|
||||
LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
|
||||
LSM_HOOK_INIT(userns_create, selinux_userns_create),
|
||||
|
||||
LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
|
||||
LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
|
||||
|
||||
@@ -255,6 +255,8 @@ const struct security_class_mapping secclass_map[] = {
|
||||
{ COMMON_FILE_PERMS, NULL } },
|
||||
{ "io_uring",
|
||||
{ "override_creds", "sqpoll", "cmd", NULL } },
|
||||
{ "user_namespace",
|
||||
{ "create", NULL } },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ struct selinux_fs_info {
|
||||
struct dentry *bool_dir;
|
||||
unsigned int bool_num;
|
||||
char **bool_pending_names;
|
||||
unsigned int *bool_pending_values;
|
||||
int *bool_pending_values;
|
||||
struct dentry *class_dir;
|
||||
unsigned long last_class_ino;
|
||||
bool policy_opened;
|
||||
@@ -356,7 +356,7 @@ static const struct file_operations sel_policyvers_ops = {
|
||||
/* declaration for sel_write_load */
|
||||
static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_dir,
|
||||
unsigned int *bool_num, char ***bool_pending_names,
|
||||
unsigned int **bool_pending_values);
|
||||
int **bool_pending_values);
|
||||
static int sel_make_classes(struct selinux_policy *newpolicy,
|
||||
struct dentry *class_dir,
|
||||
unsigned long *last_class_ino);
|
||||
@@ -527,7 +527,7 @@ static const struct file_operations sel_policy_ops = {
|
||||
};
|
||||
|
||||
static void sel_remove_old_bool_data(unsigned int bool_num, char **bool_names,
|
||||
unsigned int *bool_values)
|
||||
int *bool_values)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
@@ -545,7 +545,7 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
|
||||
struct dentry *tmp_parent, *tmp_bool_dir, *tmp_class_dir, *old_dentry;
|
||||
unsigned int tmp_bool_num, old_bool_num;
|
||||
char **tmp_bool_names, **old_bool_names;
|
||||
unsigned int *tmp_bool_values, *old_bool_values;
|
||||
int *tmp_bool_values, *old_bool_values;
|
||||
unsigned long tmp_ino = fsi->last_ino; /* Don't increment last_ino in this function */
|
||||
|
||||
tmp_parent = sel_make_disconnected_dir(fsi->sb, &tmp_ino);
|
||||
@@ -1423,7 +1423,7 @@ static void sel_remove_entries(struct dentry *de)
|
||||
|
||||
static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_dir,
|
||||
unsigned int *bool_num, char ***bool_pending_names,
|
||||
unsigned int **bool_pending_values)
|
||||
int **bool_pending_values)
|
||||
{
|
||||
int ret;
|
||||
ssize_t len;
|
||||
@@ -1917,7 +1917,6 @@ static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
|
||||
struct selinux_fs_info *fsi = sb->s_fs_info;
|
||||
struct dentry *dentry = NULL;
|
||||
struct inode *inode = NULL;
|
||||
int rc;
|
||||
|
||||
dentry = d_alloc_name(dir, "index");
|
||||
if (!dentry)
|
||||
@@ -1937,9 +1936,7 @@ static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
rc = sel_make_perm_files(newpolicy, classname, index, dentry);
|
||||
|
||||
return rc;
|
||||
return sel_make_perm_files(newpolicy, classname, index, dentry);
|
||||
}
|
||||
|
||||
static int sel_make_classes(struct selinux_policy *newpolicy,
|
||||
|
||||
@@ -38,7 +38,7 @@ static inline void mls_context_init(struct context *c)
|
||||
memset(&c->range, 0, sizeof(c->range));
|
||||
}
|
||||
|
||||
static inline int mls_context_cpy(struct context *dst, struct context *src)
|
||||
static inline int mls_context_cpy(struct context *dst, const struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -58,7 +58,7 @@ out:
|
||||
/*
|
||||
* Sets both levels in the MLS range of 'dst' to the low level of 'src'.
|
||||
*/
|
||||
static inline int mls_context_cpy_low(struct context *dst, struct context *src)
|
||||
static inline int mls_context_cpy_low(struct context *dst, const struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -78,7 +78,7 @@ out:
|
||||
/*
|
||||
* Sets both levels in the MLS range of 'dst' to the high level of 'src'.
|
||||
*/
|
||||
static inline int mls_context_cpy_high(struct context *dst, struct context *src)
|
||||
static inline int mls_context_cpy_high(struct context *dst, const struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -97,9 +97,10 @@ out:
|
||||
|
||||
|
||||
static inline int mls_context_glblub(struct context *dst,
|
||||
struct context *c1, struct context *c2)
|
||||
const struct context *c1, const struct context *c2)
|
||||
{
|
||||
struct mls_range *dr = &dst->range, *r1 = &c1->range, *r2 = &c2->range;
|
||||
struct mls_range *dr = &dst->range;
|
||||
const struct mls_range *r1 = &c1->range, *r2 = &c2->range;
|
||||
int rc = 0;
|
||||
|
||||
if (r1->level[1].sens < r2->level[0].sens ||
|
||||
@@ -127,7 +128,7 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int mls_context_cmp(struct context *c1, struct context *c2)
|
||||
static inline int mls_context_cmp(const struct context *c1, const struct context *c2)
|
||||
{
|
||||
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
|
||||
ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
|
||||
@@ -147,7 +148,7 @@ static inline void context_init(struct context *c)
|
||||
memset(c, 0, sizeof(*c));
|
||||
}
|
||||
|
||||
static inline int context_cpy(struct context *dst, struct context *src)
|
||||
static inline int context_cpy(struct context *dst, const struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -180,7 +181,7 @@ static inline void context_destroy(struct context *c)
|
||||
mls_context_destroy(c);
|
||||
}
|
||||
|
||||
static inline int context_cmp(struct context *c1, struct context *c2)
|
||||
static inline int context_cmp(const struct context *c1, const struct context *c2)
|
||||
{
|
||||
if (c1->len && c2->len)
|
||||
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
static struct kmem_cache *ebitmap_node_cachep __ro_after_init;
|
||||
|
||||
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
|
||||
int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n1, *n2;
|
||||
const struct ebitmap_node *n1, *n2;
|
||||
|
||||
if (e1->highbit != e2->highbit)
|
||||
return 0;
|
||||
@@ -50,9 +50,10 @@ int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
|
||||
int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src)
|
||||
{
|
||||
struct ebitmap_node *n, *new, *prev;
|
||||
struct ebitmap_node *new, *prev;
|
||||
const struct ebitmap_node *n;
|
||||
|
||||
ebitmap_init(dst);
|
||||
n = src->node;
|
||||
@@ -78,7 +79,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ebitmap_and(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2)
|
||||
int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
int bit, rc;
|
||||
@@ -217,9 +218,9 @@ netlbl_import_failure:
|
||||
* if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
|
||||
* last_e2bit.
|
||||
*/
|
||||
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
|
||||
int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit)
|
||||
{
|
||||
struct ebitmap_node *n1, *n2;
|
||||
const struct ebitmap_node *n1, *n2;
|
||||
int i;
|
||||
|
||||
if (e1->highbit < e2->highbit)
|
||||
@@ -258,9 +259,9 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
|
||||
int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
const struct ebitmap_node *n;
|
||||
|
||||
if (e->highbit < bit)
|
||||
return 0;
|
||||
@@ -467,7 +468,7 @@ bad:
|
||||
goto out;
|
||||
}
|
||||
|
||||
int ebitmap_write(struct ebitmap *e, void *fp)
|
||||
int ebitmap_write(const struct ebitmap *e, void *fp)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
u32 count;
|
||||
|
||||
@@ -44,7 +44,7 @@ struct ebitmap {
|
||||
|
||||
#define ebitmap_length(e) ((e)->highbit)
|
||||
|
||||
static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
|
||||
static inline unsigned int ebitmap_start_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n)
|
||||
{
|
||||
unsigned int ofs;
|
||||
@@ -62,7 +62,7 @@ static inline void ebitmap_init(struct ebitmap *e)
|
||||
memset(e, 0, sizeof(*e));
|
||||
}
|
||||
|
||||
static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
|
||||
static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n,
|
||||
unsigned int bit)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
|
||||
#define EBITMAP_NODE_OFFSET(node, bit) \
|
||||
(((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
|
||||
|
||||
static inline int ebitmap_node_get_bit(struct ebitmap_node *n,
|
||||
static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
|
||||
unsigned int bit)
|
||||
{
|
||||
unsigned int index = EBITMAP_NODE_INDEX(n, bit);
|
||||
@@ -122,15 +122,15 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
|
||||
(bit) < ebitmap_length(e); \
|
||||
(bit) = ebitmap_next_positive(e, &(n), bit)) \
|
||||
|
||||
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
|
||||
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
|
||||
int ebitmap_and(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2);
|
||||
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit);
|
||||
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
|
||||
int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2);
|
||||
int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src);
|
||||
int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2);
|
||||
int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit);
|
||||
int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit);
|
||||
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
|
||||
void ebitmap_destroy(struct ebitmap *e);
|
||||
int ebitmap_read(struct ebitmap *e, void *fp);
|
||||
int ebitmap_write(struct ebitmap *e, void *fp);
|
||||
int ebitmap_write(const struct ebitmap *e, void *fp);
|
||||
u32 ebitmap_hash(const struct ebitmap *e, u32 hash);
|
||||
|
||||
#ifdef CONFIG_NETLABEL
|
||||
|
||||
@@ -27,13 +27,13 @@ struct mls_range {
|
||||
struct mls_level level[2]; /* low == level[0], high == level[1] */
|
||||
};
|
||||
|
||||
static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
|
||||
static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2)
|
||||
{
|
||||
return ((l1->sens == l2->sens) &&
|
||||
ebitmap_cmp(&l1->cat, &l2->cat));
|
||||
}
|
||||
|
||||
static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
|
||||
static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2)
|
||||
{
|
||||
return ((l1->sens >= l2->sens) &&
|
||||
ebitmap_contains(&l1->cat, &l2->cat, 0));
|
||||
|
||||
@@ -180,15 +180,6 @@ struct smack_known_list_elem {
|
||||
struct smack_known *smk_label;
|
||||
};
|
||||
|
||||
/* Super block security struct flags for mount options */
|
||||
#define FSDEFAULT_MNT 0x01
|
||||
#define FSFLOOR_MNT 0x02
|
||||
#define FSHAT_MNT 0x04
|
||||
#define FSROOT_MNT 0x08
|
||||
#define FSTRANS_MNT 0x10
|
||||
|
||||
#define NUM_SMK_MNT_OPTS 5
|
||||
|
||||
enum {
|
||||
Opt_error = -1,
|
||||
Opt_fsdefault = 0,
|
||||
|
||||
@@ -497,13 +497,11 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
|
||||
*/
|
||||
static int smack_ptrace_traceme(struct task_struct *ptp)
|
||||
{
|
||||
int rc;
|
||||
struct smack_known *skp;
|
||||
|
||||
skp = smk_of_task(smack_cred(current_cred()));
|
||||
|
||||
rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
|
||||
return rc;
|
||||
return smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2279,6 +2277,21 @@ static void smack_sk_free_security(struct sock *sk)
|
||||
kfree(sk->sk_security);
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_sk_clone_security - Copy security context
|
||||
* @sk: the old socket
|
||||
* @newsk: the new socket
|
||||
*
|
||||
* Copy the security context of the old socket pointer to the cloned
|
||||
*/
|
||||
static void smack_sk_clone_security(const struct sock *sk, struct sock *newsk)
|
||||
{
|
||||
struct socket_smack *ssp_old = sk->sk_security;
|
||||
struct socket_smack *ssp_new = newsk->sk_security;
|
||||
|
||||
*ssp_new = *ssp_old;
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_ipv4host_label - check host based restrictions
|
||||
* @sip: the object end
|
||||
@@ -4882,6 +4895,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
|
||||
LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
|
||||
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
|
||||
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
|
||||
LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security),
|
||||
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
|
||||
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
|
||||
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define _GNU_SOURCE
|
||||
#include <test_progs.h>
|
||||
#include "test_deny_namespace.skel.h"
|
||||
#include <sched.h>
|
||||
#include "cap_helpers.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static int wait_for_pid(pid_t pid)
|
||||
{
|
||||
int status, ret;
|
||||
|
||||
again:
|
||||
ret = waitpid(pid, &status, 0);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!WIFEXITED(status))
|
||||
return -1;
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
/* negative return value -> some internal error
|
||||
* positive return value -> userns creation failed
|
||||
* 0 -> userns creation succeeded
|
||||
*/
|
||||
static int create_user_ns(void)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
return -1;
|
||||
|
||||
if (pid == 0) {
|
||||
if (unshare(CLONE_NEWUSER))
|
||||
_exit(EXIT_FAILURE);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
return wait_for_pid(pid);
|
||||
}
|
||||
|
||||
static void test_userns_create_bpf(void)
|
||||
{
|
||||
__u32 cap_mask = 1ULL << CAP_SYS_ADMIN;
|
||||
__u64 old_caps = 0;
|
||||
|
||||
cap_enable_effective(cap_mask, &old_caps);
|
||||
|
||||
ASSERT_OK(create_user_ns(), "priv new user ns");
|
||||
|
||||
cap_disable_effective(cap_mask, &old_caps);
|
||||
|
||||
ASSERT_EQ(create_user_ns(), EPERM, "unpriv new user ns");
|
||||
|
||||
if (cap_mask & old_caps)
|
||||
cap_enable_effective(cap_mask, NULL);
|
||||
}
|
||||
|
||||
static void test_unpriv_userns_create_no_bpf(void)
|
||||
{
|
||||
__u32 cap_mask = 1ULL << CAP_SYS_ADMIN;
|
||||
__u64 old_caps = 0;
|
||||
|
||||
cap_disable_effective(cap_mask, &old_caps);
|
||||
|
||||
ASSERT_OK(create_user_ns(), "no-bpf unpriv new user ns");
|
||||
|
||||
if (cap_mask & old_caps)
|
||||
cap_enable_effective(cap_mask, NULL);
|
||||
}
|
||||
|
||||
void test_deny_namespace(void)
|
||||
{
|
||||
struct test_deny_namespace *skel = NULL;
|
||||
int err;
|
||||
|
||||
if (test__start_subtest("unpriv_userns_create_no_bpf"))
|
||||
test_unpriv_userns_create_no_bpf();
|
||||
|
||||
skel = test_deny_namespace__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel load"))
|
||||
goto close_prog;
|
||||
|
||||
err = test_deny_namespace__attach(skel);
|
||||
if (!ASSERT_OK(err, "attach"))
|
||||
goto close_prog;
|
||||
|
||||
if (test__start_subtest("userns_create_bpf"))
|
||||
test_userns_create_bpf();
|
||||
|
||||
test_deny_namespace__detach(skel);
|
||||
|
||||
close_prog:
|
||||
test_deny_namespace__destroy(skel);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <errno.h>
|
||||
#include <linux/capability.h>
|
||||
|
||||
struct kernel_cap_struct {
|
||||
__u32 cap[_LINUX_CAPABILITY_U32S_3];
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct cred {
|
||||
struct kernel_cap_struct cap_effective;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
SEC("lsm.s/userns_create")
|
||||
int BPF_PROG(test_userns_create, const struct cred *cred, int ret)
|
||||
{
|
||||
struct kernel_cap_struct caps = cred->cap_effective;
|
||||
int cap_index = CAP_TO_INDEX(CAP_SYS_ADMIN);
|
||||
__u32 cap_mask = CAP_TO_MASK(CAP_SYS_ADMIN);
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
ret = -EPERM;
|
||||
if (caps.cap[cap_index] & cap_mask)
|
||||
return 0;
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
Reference in New Issue
Block a user