Commit c54b245d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull user namespace rlimit handling update from Eric Biederman:
 "This is the work mainly by Alexey Gladkov to limit rlimits to the
  rlimits of the user that created a user namespace, and to allow users
  to have stricter limits on the resources created within a user
  namespace."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  cred: add missing return error code when set_cred_ucounts() failed
  ucounts: Silence warning in dec_rlimit_ucounts
  ucounts: Set ucount_max to the largest positive value the type can hold
  kselftests: Add test to check for rlimit changes in different user namespaces
  Reimplement RLIMIT_MEMLOCK on top of ucounts
  Reimplement RLIMIT_SIGPENDING on top of ucounts
  Reimplement RLIMIT_MSGQUEUE on top of ucounts
  Reimplement RLIMIT_NPROC on top of ucounts
  Use atomic_t for ucounts reference counting
  Add a reference to ucounts for each cred
  Increase size of ucounts to atomic_long_t
parents e17c120f 5e6b8a50
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -1360,6 +1360,10 @@ int begin_new_exec(struct linux_binprm * bprm)
	WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
	flush_signal_handlers(me, 0);

	retval = set_cred_ucounts(bprm->cred);
	if (retval < 0)
		goto out_unlock;

	/*
	 * install the new credentials for this executable
	 */
@@ -1874,7 +1878,7 @@ static int do_execveat_common(int fd, struct filename *filename,
	 * whether NPROC limit is still exceeded.
	 */
	if ((current->flags & PF_NPROC_EXCEEDED) &&
	    atomic_read(&current_user()->processes) > rlimit(RLIMIT_NPROC)) {
	    is_ucounts_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
		retval = -EAGAIN;
		goto out_ret;
	}
+8 −8
Original line number Diff line number Diff line
@@ -1446,7 +1446,7 @@ static int get_hstate_idx(int page_size_log)
 * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
 */
struct file *hugetlb_file_setup(const char *name, size_t size,
				vm_flags_t acctflag, struct user_struct **user,
				vm_flags_t acctflag, struct ucounts **ucounts,
				int creat_flags, int page_size_log)
{
	struct inode *inode;
@@ -1458,20 +1458,20 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
	if (hstate_idx < 0)
		return ERR_PTR(-ENODEV);

	*user = NULL;
	*ucounts = NULL;
	mnt = hugetlbfs_vfsmount[hstate_idx];
	if (!mnt)
		return ERR_PTR(-ENOENT);

	if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
		*user = current_user();
		if (user_shm_lock(size, *user)) {
		*ucounts = current_ucounts();
		if (user_shm_lock(size, *ucounts)) {
			task_lock(current);
			pr_warn_once("%s (%d): Using mlock ulimits for SHM_HUGETLB is deprecated\n",
				current->comm, current->pid);
			task_unlock(current);
		} else {
			*user = NULL;
			*ucounts = NULL;
			return ERR_PTR(-EPERM);
		}
	}
@@ -1498,9 +1498,9 @@ struct file *hugetlb_file_setup(const char *name, size_t size,

	iput(inode);
out:
	if (*user) {
		user_shm_unlock(size, *user);
		*user = NULL;
	if (*ucounts) {
		user_shm_unlock(size, *ucounts);
		*ucounts = NULL;
	}
	return file;
}
+1 −1
Original line number Diff line number Diff line
@@ -284,7 +284,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
		collect_sigign_sigcatch(p, &ignored, &caught);
		num_threads = get_nr_threads(p);
		rcu_read_lock();  /* FIXME: is this correct? */
		qsize = atomic_read(&__task_cred(p)->user->sigpending);
		qsize = get_ucounts_value(task_ucounts(p), UCOUNT_RLIMIT_SIGPENDING);
		rcu_read_unlock();
		qlim = task_rlimit(p, RLIMIT_SIGPENDING);
		unlock_task_sighand(p, &flags);
+4 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ struct cred {
#endif
	struct user_struct *user;	/* real user ID subscription */
	struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
	struct ucounts *ucounts;
	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
	/* RCU deletion */
	union {
@@ -169,6 +170,7 @@ extern int set_security_override_from_ctx(struct cred *, const char *);
extern int set_create_files_as(struct cred *, struct inode *);
extern int cred_fscmp(const struct cred *, const struct cred *);
extern void __init cred_init(void);
extern int set_cred_ucounts(struct cred *);

/*
 * check for validity of credentials
@@ -369,6 +371,7 @@ static inline void put_cred(const struct cred *_cred)

#define task_uid(task)		(task_cred_xxx((task), uid))
#define task_euid(task)		(task_cred_xxx((task), euid))
#define task_ucounts(task)	(task_cred_xxx((task), ucounts))

#define current_cred_xxx(xxx)			\
({						\
@@ -385,6 +388,7 @@ static inline void put_cred(const struct cred *_cred)
#define current_fsgid() 	(current_cred_xxx(fsgid))
#define current_cap()		(current_cred_xxx(cap_effective))
#define current_user()		(current_cred_xxx(user))
#define current_ucounts()	(current_cred_xxx(ucounts))

extern struct user_namespace init_user_ns;
#ifdef CONFIG_USER_NS
+2 −2
Original line number Diff line number Diff line
@@ -451,7 +451,7 @@ static inline struct hugetlbfs_inode_info *HUGETLBFS_I(struct inode *inode)
extern const struct file_operations hugetlbfs_file_operations;
extern const struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct,
				struct user_struct **user, int creat_flags,
				struct ucounts **ucounts, int creat_flags,
				int page_size_log);

static inline bool is_file_hugepages(struct file *file)
@@ -471,7 +471,7 @@ static inline struct hstate *hstate_inode(struct inode *i)
#define is_file_hugepages(file)			false
static inline struct file *
hugetlb_file_setup(const char *name, size_t size, vm_flags_t acctflag,
		struct user_struct **user, int creat_flags,
		struct ucounts **ucounts, int creat_flags,
		int page_size_log)
{
	return ERR_PTR(-ENOSYS);
Loading