Issues with Linux kernel oplocks

J. Bruce Fields bfields at fieldses.org
Wed Jul 24 06:50:18 MDT 2013


On Tue, Jul 23, 2013 at 02:53:04PM -0700, Jeremy Allison wrote:
> On Tue, Jul 23, 2013 at 02:12:28PM -0700, Jeremy Allison wrote:
> > On Tue, Jul 23, 2013 at 05:01:15PM -0400, J. Bruce Fields wrote:
> > > On Tue, Jul 23, 2013 at 01:47:30PM -0700, Jeremy Allison wrote:
> > > > On Tue, Jul 23, 2013 at 04:32:16PM -0400, J. Bruce Fields wrote:
> > > > > 
> > > > > Sure, but...
> > > > > 
> > > > > > Neither process has to be privileged, neither
> > > > > > process has to have changed uids.
> > > > > > 
> > > > > > For leases to work this condition:
> > > > > > 
> > > > > > "the real or effective user ID of the sending process must equal
> > > > > > the real or saved set-user-ID of the target process."
> > > > > > 
> > > > > > cannot be correct. Else you could only break leases between
> > > > > > processes who are owned by the same uid - or from a privileged
> > > > > > opener.
> > > > > 
> > > > > ... you're confusing the lease-breaker and the lease-setter.
> > > > > 
> > > > > Note in the first quote above, "where the sending process is the one
> > > > > that employs F_SETOWN".  (Or equivalently, I think, F_SETLEASE.)
> > > > 
> > > > Ok then I'm really confused. Samba always does
> > > > the lease set as the same uid as the open, we
> > > > never change uids between the open and the
> > > > setting of the kernel oplock.
> > > 
> > > Right, so both are done with uid X.  But then later when the lease break
> > > happens the signal is sent to the thread that did the open.  And that
> > > signal is treated as if it's coming from uid X.  The thread may have
> > > changed uid's, and that may not work.
> > > 
> > > (OK, "uid" isn't quite right, see the kill(2) language for the actual
> > > uid's involved.)
> > 
> > Ah - I get it ! Thanks.
> > 
> > Ok, so the fix inside Samba would be to become_root()/unbecome_root()
> > around the kernel oplock set call to ensure that the uid of the
> > sending process is always 0 and will always have the rights to
> > send the signal.

Good, that makes sense to me....

--b.

> > 
> > That's actually quite an easy fix - more so than playing
> > games with a receiver thread.
> 
> Ok Ralph, can you test this fix to see if it addresses
> your issue ? It should apply cleanly to 3.6.x and 4.0.x.
> 
> If it works for you then we'll raise a bug and get it
> into 3.6.next and 4.0.next.
> 
> Cheers,
> 
> 	Jeremy.

> diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
> index 7fa9b7c..2d2b21d 100644
> --- a/source3/smbd/oplock_linux.c
> +++ b/source3/smbd/oplock_linux.c
> @@ -75,26 +75,28 @@ int linux_set_lease_sighandler(int fd)
>  int linux_setlease(int fd, int leasetype)
>  {
>  	int ret;
> +	int saved_errno;
> +
> +	become_root();
>  
>  	/* First set the signal handler. */
>  	if (linux_set_lease_sighandler(fd) == -1) {
> -		return -1;
> +		saved_errno = errno;
> +		ret = -1;
> +		goto out;
>  	}
>  	ret = fcntl(fd, F_SETLEASE, leasetype);
> -	if (ret == -1 && errno == EACCES) {
> -		set_effective_capability(LEASE_CAPABILITY);
> -		/*
> -		 * Bug 8974 - work around Linux kernel bug
> -		 * https://bugzilla.kernel.org/show_bug.cgi?id=43336.
> -		 * "fcntl(F_SETLEASE) resets signal number when
> -		 *  called multiple times"
> -		 */
> -		if (linux_set_lease_sighandler(fd) == -1) {
> -			return -1;
> -		}
> -		ret = fcntl(fd, F_SETLEASE, leasetype);
> +	if (ret == -1) {
> +		saved_errno = errno;
>  	}
>  
> +  out:
> +
> +	unbecome_root();
> +
> +	if (ret == -1) {
> +		errno = saved_errno;
> +	}
>  	return ret;
>  }
>  



More information about the samba-technical mailing list