mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-10-31 18:09:19 +00:00
1c587ee50e
commit 9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8 upstream. - Expose the knob to user space through a proc file /proc/<pid>/setgroups A value of "deny" means the setgroups system call is disabled in the current processes user namespace and can not be enabled in the future in this user namespace. A value of "allow" means the segtoups system call is enabled. - Descendant user namespaces inherit the value of setgroups from their parents. - A proc file is used (instead of a sysctl) as sysctls currently do not allow checking the permissions at open time. - Writing to the proc file is restricted to before the gid_map for the user namespace is set. This ensures that disabling setgroups at a user namespace level will never remove the ability to call setgroups from a process that already has that ability. A process may opt in to the setgroups disable for itself by creating, entering and configuring a user namespace or by calling setns on an existing user namespace with setgroups disabled. Processes without privileges already can not call setgroups so this is a noop. Prodcess with privilege become processes without privilege when entering a user namespace and as with any other path to dropping privilege they would not have the ability to call setgroups. So this remains within the bounds of what is possible without a knob to disable setgroups permanently in a user namespace. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
102 lines
2.5 KiB
C
102 lines
2.5 KiB
C
#ifndef _LINUX_USER_NAMESPACE_H
|
|
#define _LINUX_USER_NAMESPACE_H
|
|
|
|
#include <linux/kref.h>
|
|
#include <linux/nsproxy.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/err.h>
|
|
|
|
#define UID_GID_MAP_MAX_EXTENTS 5
|
|
|
|
struct uid_gid_map { /* 64 bytes -- 1 cache line */
|
|
u32 nr_extents;
|
|
struct uid_gid_extent {
|
|
u32 first;
|
|
u32 lower_first;
|
|
u32 count;
|
|
} extent[UID_GID_MAP_MAX_EXTENTS];
|
|
};
|
|
|
|
#define USERNS_SETGROUPS_ALLOWED 1UL
|
|
|
|
#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED
|
|
|
|
struct user_namespace {
|
|
struct uid_gid_map uid_map;
|
|
struct uid_gid_map gid_map;
|
|
struct uid_gid_map projid_map;
|
|
atomic_t count;
|
|
struct user_namespace *parent;
|
|
int level;
|
|
kuid_t owner;
|
|
kgid_t group;
|
|
unsigned int proc_inum;
|
|
unsigned long flags;
|
|
bool may_mount_sysfs;
|
|
bool may_mount_proc;
|
|
};
|
|
|
|
extern struct user_namespace init_user_ns;
|
|
|
|
#ifdef CONFIG_USER_NS
|
|
|
|
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
|
{
|
|
if (ns)
|
|
atomic_inc(&ns->count);
|
|
return ns;
|
|
}
|
|
|
|
extern int create_user_ns(struct cred *new);
|
|
extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred);
|
|
extern void free_user_ns(struct user_namespace *ns);
|
|
|
|
static inline void put_user_ns(struct user_namespace *ns)
|
|
{
|
|
if (ns && atomic_dec_and_test(&ns->count))
|
|
free_user_ns(ns);
|
|
}
|
|
|
|
struct seq_operations;
|
|
extern struct seq_operations proc_uid_seq_operations;
|
|
extern struct seq_operations proc_gid_seq_operations;
|
|
extern struct seq_operations proc_projid_seq_operations;
|
|
extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
|
|
extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
|
|
extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *);
|
|
extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
|
|
extern int proc_setgroups_show(struct seq_file *m, void *v);
|
|
extern bool userns_may_setgroups(const struct user_namespace *ns);
|
|
#else
|
|
|
|
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
|
{
|
|
return &init_user_ns;
|
|
}
|
|
|
|
static inline int create_user_ns(struct cred *new)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int unshare_userns(unsigned long unshare_flags,
|
|
struct cred **new_cred)
|
|
{
|
|
if (unshare_flags & CLONE_NEWUSER)
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
static inline void put_user_ns(struct user_namespace *ns)
|
|
{
|
|
}
|
|
|
|
static inline bool userns_may_setgroups(const struct user_namespace *ns)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
void update_mnt_policy(struct user_namespace *userns);
|
|
|
|
#endif /* _LINUX_USER_H */
|