mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Chris Wright <chrisw@osdl.org>
To: Rik van Riel <riel@redhat.com>
Cc: William Lee Irwin III <wli@holomorphy.com>,
	Andrea Arcangeli <andrea@suse.de>, Chris Wright <chrisw@osdl.org>,
	Arjan van de Ven <arjanv@redhat.com>,
	linux-kernel@vger.kernel.org, Andrew Morton <akpm@osdl.org>
Subject: Re: [patch] mlock-as-nonroot revisted
Date: Tue, 3 Aug 2004 23:06:14 -0700	[thread overview]
Message-ID: <20040803230614.C1924@build.pdx.osdl.net> (raw)
In-Reply-To: <Pine.LNX.4.44.0408032254250.32641-100000@dhcp83-102.boston.redhat.com>; from riel@redhat.com on Tue, Aug 03, 2004 at 10:56:15PM -0400

* Rik van Riel (riel@redhat.com) wrote:
> On Tue, 3 Aug 2004, William Lee Irwin III wrote:
> 
> > By any chance could you repost a complete patch and/or series?
> 
> Here you are.  It is fits into the Fedora kernel rpm, but
> I guess it should apply to upstream and -mm too.

Not quite.  The hugetlb_shm_group change is upstream so there's a small
conflict.  I've got a diff.  It begs the question of whether to keep
the hugetlb_shm_group bits at all if this is merged.

> Please check if there are any spots left where this patch
> did something wrong. I'd like to get this merged ASAP, so
> I will fix any actual errors people find.

Few spots below.

> --- linux-2.6.7/ipc/shm.c.mlock	2004-08-03 22:46:29.848674505 -0400
> +++ linux-2.6.7/ipc/shm.c	2004-08-03 22:46:43.399678929 -0400
> @@ -114,7 +114,10 @@ static void shm_destroy (struct shmid_ke
>  	shm_rmid (shp->id);
>  	shm_unlock(shp);
>  	if (!is_file_hugepages(shp->shm_file))
> -		shmem_lock(shp->shm_file, 0);
> +		shmem_lock(shp->shm_file, 0, shp->mlock_user);
> +	else
> +		user_subtract_mlock(shp->shm_file->f_dentry->d_inode->i_size,
> +						shp->mlock_user);
>  	fput (shp->shm_file);
>  	security_shm_free(shp);
>  	ipc_rcu_free(shp, sizeof(struct shmid_kernel));
> @@ -198,9 +201,11 @@ static int newseg (key_t key, int shmflg
>  		return error;
>  	}
>  
> -	if (shmflg & SHM_HUGETLB)
> +	if (shmflg & SHM_HUGETLB) {
> +		/* hugetlb_zero_setup takes care of mlock user accounting */
>  		file = hugetlb_zero_setup(size);
> -	else {
> +		shp->mlock_user = current->user;

This gets overwritten by NULL in the hunk below.  So the accouting will
never be undone.

> +	} else {
>  		sprintf (name, "SYSV%08x", key);
>  		file = shmem_file_setup(name, size, VM_ACCOUNT);
>  	}
> @@ -221,6 +226,7 @@ static int newseg (key_t key, int shmflg
>  	shp->shm_nattch = 0;
>  	shp->id = shm_buildid(id,shp->shm_perm.seq);
>  	shp->shm_file = file;
> +	shp->mlock_user = NULL;
>  	file->f_dentry->d_inode->i_ino = shp->id;
>  	if (shmflg & SHM_HUGETLB)
>  		set_file_hugepages(file);
> @@ -504,14 +510,11 @@ asmlinkage long sys_shmctl (int shmid, i
>  	case SHM_LOCK:
>  	case SHM_UNLOCK:
>  	{
> -/* Allow superuser to lock segment in memory */
> -/* Should the pages be faulted in here or leave it to user? */
> -/* need to determine interaction with current->swappable */
> -		if (!capable(CAP_IPC_LOCK)) {
> +		/* Allow superuser to lock segment in memory */
> +		if (!can_do_mlock()) {

I actually think this is too restrictive.  Why not be able
to unlock is the rlimit has been reset to zero?  It's also
called 2 or 3 times during SHM_LOCK.

>  			err = -EPERM;
>  			goto out;
>  		}
> -
>  		shp = shm_lock(shmid);
>  		if(shp==NULL) {
>  			err = -EINVAL;
> @@ -526,13 +529,19 @@ asmlinkage long sys_shmctl (int shmid, i
>  			goto out_unlock;
>  		
>  		if(cmd==SHM_LOCK) {
> -			if (!is_file_hugepages(shp->shm_file))
> -				shmem_lock(shp->shm_file, 1);
> -			shp->shm_flags |= SHM_LOCKED;
> +			struct user_struct * user = current->user;
> +			if (!is_file_hugepages(shp->shm_file)) {
> +				err = shmem_lock(shp->shm_file, 1, current->user);
> +				if (!err) {
> +					shp->shm_flags |= SHM_LOCKED;

Slight change in behaviour.  Used to set SHM_LOCKED on hugetlb backed
segments as well.  I don't see any purpose for the old behaviour though.

> +					shp->mlock_user = user;
> +				}
> +			}
>  		} else {
>  			if (!is_file_hugepages(shp->shm_file))
> -				shmem_lock(shp->shm_file, 0);
> +				shmem_lock(shp->shm_file, 0, shp->mlock_user);
>  			shp->shm_flags &= ~SHM_LOCKED;

This doesn't match behaviour above.

> +			shp->mlock_user = NULL;

This means that SHM_UNLOCK on SHM_HUGETLB segment will never get unaccounted
during segment destruction (since mlock_user will errnoeously be NULL).  I
think both of these should be under !is_file_hugepages condition.  I don't
see the point of SHM_{UN,}LOCK on SHM_HUGETLB segment.

>  		}
>  		shm_unlock(shp);
>  		goto out;
> --- linux-2.6.7/ipc/util.c.mlock	2004-08-03 22:46:29.851673621 -0400
> +++ linux-2.6.7/ipc/util.c	2004-08-03 22:46:43.402678045 -0400
> @@ -392,8 +392,11 @@ int ipcperms (struct kern_ipc_perm *ipcp
>  		granted_mode >>= 3;
>  	/* is there some bit set in requested_mode but not in granted_mode? */
>  	if ((requested_mode & ~granted_mode & 0007) && 
> -	    !capable(CAP_IPC_OWNER))
> -		return -1;
> +	    !capable(CAP_IPC_OWNER)) {
> +		if (!can_do_mlock())  {
> +			return -1;
> +		}
> +	}	

I still don't see the use for this one.  I believe it duplicates
SHM_HUGETLB check that's already there.

> +int user_can_mlock(size_t size, struct user_struct * user)
> +{
> +	unsigned long lock_limit, locked;
> +	int allowed = 0;
> +
> +	spin_lock(&mlock_user_lock);
> +	locked = size >> PAGE_SHIFT;
> +	lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
> +	lock_limit >>= PAGE_SHIFT;
> +	if (locked + user->locked_shm > lock_limit)
> +		goto out;
> +	atomic_inc(&user->__count);

There is a trivial get_uid wrapper.  Although, that's arguable whether
it's useful here.

> +	user->locked_shm += locked;
> +	allowed = 1;
> +out:
> +	spin_unlock(&mlock_user_lock);
> +	return allowed;
> +}
> +
> +void user_subtract_mlock(size_t size, struct user_struct * user)
> +{
> +	if (user) {

Hmm, is !user ever valid?  Perhaps it should start out as BUG_ON?

> +		spin_lock(&mlock_user_lock);
> +		user->locked_shm -= (size >> PAGE_SHIFT);
> +		spin_unlock(&mlock_user_lock);
> +		free_uid(user);
> +	}
> +}
> --- linux-2.6.7/mm/shmem.c.mlock	2004-08-03 22:46:39.416853287 -0400
> +++ linux-2.6.7/mm/shmem.c	2004-08-03 22:46:43.444665665 -0400
> @@ -1151,17 +1151,29 @@ shmem_get_policy(struct vm_area_struct *
>  }
>  #endif
>  
> -void shmem_lock(struct file *file, int lock)
> +int shmem_lock(struct file *file, int lock, struct user_struct * user)
>  {
>  	struct inode *inode = file->f_dentry->d_inode;
>  	struct shmem_inode_info *info = SHMEM_I(inode);
> +	int retval = -ENOMEM;
> +
> +	if (!can_do_mlock())
> +		return -EPERM;

I see no point in checking this when !lock.  In fact, the error will
be silently ignored, and the accounting will never be undone if ulimit
is reset to 0 before removing the segment.  In the case of lock ==
1, user_can_mlock basically duplicates the check.  Maybe it should
just be removed.

>  	spin_lock(&info->lock);
> -	if (lock)
> +	if (lock && !(info->flags & VM_LOCKED)) {
> +		if (!user_can_mlock(inode->i_size, user) && !capable(CAP_IPC_LOCK))
> +			goto out_nomem;
>  		info->flags |= VM_LOCKED;
> -	else
> +	}
> +	if (!lock && (info->flags & VM_LOCKED) && user) {
> +		user_subtract_mlock(inode->i_size, user);
>  		info->flags &= ~VM_LOCKED;
> +	}
> +	retval = 0;
> +out_nomem:
>  	spin_unlock(&info->lock);
> +	return retval;
>  }
>  
>  static int shmem_mmap(struct file *file, struct vm_area_struct *vma)

-- 
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net

  reply	other threads:[~2004-08-04  6:06 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-07-29 10:03 Arjan van de Ven
2004-07-29 21:28 ` Andrew Morton
2004-07-29 21:40   ` Andrea Arcangeli
2004-07-30  0:50     ` Rik van Riel
2004-07-30  2:16       ` Andrea Arcangeli
2004-07-30  0:51   ` Rik van Riel
2004-07-30  2:17     ` Andrea Arcangeli
2004-07-30  1:52 ` Chris Wright
2004-07-30  2:09   ` Andrea Arcangeli
2004-07-30  2:46   ` Rik van Riel
2004-08-03 20:54   ` Rik van Riel
2004-08-03 21:45     ` Chris Wright
2004-08-03 20:55   ` Rik van Riel
2004-08-03 21:07     ` Andrea Arcangeli
2004-08-03 21:13       ` Arjan van de Ven
2004-08-03 21:36         ` Andrea Arcangeli
2004-08-03 21:38           ` Arjan van de Ven
2004-08-03 21:51             ` Andrea Arcangeli
2004-08-03 22:01               ` Chris Wright
2004-08-03 22:11                 ` Andrea Arcangeli
2004-08-03 22:33                   ` Chris Wright
2004-08-03 22:42                     ` Andrea Arcangeli
2004-08-03 22:52                       ` Chris Wright
2004-08-04  1:21                   ` Rik van Riel
2004-08-04  1:53                     ` Andrea Arcangeli
2004-08-04  2:01                       ` Rik van Riel
2004-08-04  2:13                         ` Andrea Arcangeli
2004-08-04  2:20                           ` William Lee Irwin III
2004-08-04  2:22                           ` Rik van Riel
2004-08-04  2:31                             ` William Lee Irwin III
2004-08-04  2:56                               ` Rik van Riel
2004-08-04  6:06                                 ` Chris Wright [this message]
2004-08-04 13:31                                   ` Rik van Riel
2004-08-04 13:51                                     ` Arjan van de Ven
2004-08-04 13:56                                       ` Rik van Riel
2004-08-04  3:13                             ` Andrea Arcangeli
2004-08-04  2:25                           ` Chris Wright
2004-08-04  2:07                       ` Chris Wright
2004-08-04  2:18                         ` Andrea Arcangeli
2004-08-03 21:13       ` Rik van Riel
2004-08-03 21:22         ` Andrea Arcangeli
2004-08-03 21:24           ` Arjan van de Ven
2004-08-03 21:31           ` Rik van Riel
2004-08-03 21:39             ` Andrea Arcangeli
2004-08-04  1:56               ` William Lee Irwin III
2004-08-03 22:18             ` Gerrit Huizenga
2004-08-04  1:22               ` Rik van Riel
2004-08-04  1:37                 ` Gerrit Huizenga
2004-08-04  1:55                   ` William Lee Irwin III

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040803230614.C1924@build.pdx.osdl.net \
    --to=chrisw@osdl.org \
    --cc=akpm@osdl.org \
    --cc=andrea@suse.de \
    --cc=arjanv@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=riel@redhat.com \
    --cc=wli@holomorphy.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®