linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Michael Kerrisk <mtk.manpages@googlemail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>,
	lkml <linux-kernel@vger.kernel.org>,
	Christoph Hellwig <hch@lst.de>,
	Miklos Szeredi <miklos@szeredi.hu>,
	Al Viro <viro@zeniv.linux.org.uk>,
	jamie@shareable.org, Ulrich Drepper <drepper@redhat.com>,
	linux-fsdevel@vger.kernel.org,
	Subrata Modak <subrata@linux.vnet.ibm.com>
Subject: utimensat() non-conformances and fixes [v4] (patch)
Date: Tue, 03 Jun 2008 22:13:58 +0200	[thread overview]
Message-ID: <4845A606.6070005@gmail.com> (raw)
In-Reply-To: <48454F1D.6060507@gmail.com>

Andrew,

This patch fixes all of the utimensat() bugs outlined in my
previous mail.

I could have split the patch out into a few pieces, but given
that it is not long, and all against a single file, I've made
one patch.  Let me know if you would like separate patches for
the pieces below.

Miklos suggested an alternative idea, migrating the
is_owner_or_cap() check into fs/attr.c:inode_change_ok() via
the use of an ATTR_OWNER_CHECK flag.  Maybe we could do that
later, but for now I've one with this version, which is
simpler, and can be more easily read as being correct.

Roughly, the changes accomplish the following:

==
@@ -102,11 +97,15 @@

Addresses bug 4, and simplifies the code, since the
times == NULL and times == {UTIME_NOW, UTIME_NOW} should,
according to the POSIX.1 draft, be exactly equivalent.

==
@@ -131,15 +130,16 @@
[...]
 		if (!is_owner_or_cap(inode)) {
 			if (f) {
-				if (!(f->f_mode & FMODE_WRITE))
+				error = permission(inode, MAY_WRITE, NULL);
+				if (error)

Addresses bug 2.

==
@@ -169,14 +182,6 @@

Addresses bug 3.

==
@@ -147,7 +147,20 @@

Addresses bug 1

==

The patch also

a) removes the now unneeded nsec_special() helper function.

b) Makes a whitespace cleanup (tabs instead of spaces).

==

Thanks to Miklos, who's comments helped me improve and complete
the patch.

Cheers,

Michael


Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>

--- linux-2.6.26-rc4/fs/utimes.c	2008-05-27 14:24:13.000000000 +0200
+++ linux-2.6.26-rc4-utimensat-fix-v4/fs/utimes.c	2008-06-03 15:38:53.000000000 +0200
@@ -40,14 +40,9 @@

 #endif

-static bool nsec_special(long nsec)
-{
-	return nsec == UTIME_OMIT || nsec == UTIME_NOW;
-}
-
 static bool nsec_valid(long nsec)
 {
-	if (nsec_special(nsec))
+	if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
 		return true;

 	return nsec >= 0 && nsec <= 999999999;
@@ -102,11 +97,15 @@
 	if (error)
 		goto dput_and_out;

+	if (times && times[0].tv_nsec == UTIME_NOW &&
+		     times[1].tv_nsec == UTIME_NOW)
+		times = NULL;
+
 	/* Don't worry, the checks are done in inode_change_ok() */
 	newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 	if (times) {
 		error = -EPERM;
-                if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 			goto mnt_drop_write_and_out;

 		if (times[0].tv_nsec == UTIME_OMIT)
@@ -131,15 +130,16 @@
 	 * UTIME_NOW, then need to check permissions, because
 	 * inode_change_ok() won't do it.
 	 */
-	if (!times || (nsec_special(times[0].tv_nsec) &&
-		       nsec_special(times[1].tv_nsec))) {
+	if (!times) {
 		error = -EACCES;
+
                 if (IS_IMMUTABLE(inode))
 			goto mnt_drop_write_and_out;

 		if (!is_owner_or_cap(inode)) {
 			if (f) {
-				if (!(f->f_mode & FMODE_WRITE))
+				error = permission(inode, MAY_WRITE, NULL);
+				if (error)
 					goto mnt_drop_write_and_out;
 			} else {
 				error = vfs_permission(&nd, MAY_WRITE);
@@ -147,7 +147,20 @@
 					goto mnt_drop_write_and_out;
 			}
 		}
+	} else if ((times[0].tv_nsec == UTIME_NOW &&
+		    times[1].tv_nsec == UTIME_OMIT)
+		  ||
+		   (times[0].tv_nsec == UTIME_OMIT &&
+		    times[1].tv_nsec == UTIME_NOW)) {
+		error =-EPERM;
+
+		if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+			goto mnt_drop_write_and_out;
+
+		if (!is_owner_or_cap(inode))
+			goto mnt_drop_write_and_out;
 	}
+
 	mutex_lock(&inode->i_mutex);
 	error = notify_change(dentry, &newattrs);
 	mutex_unlock(&inode->i_mutex);
@@ -169,14 +182,6 @@
 	if (utimes) {
 		if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
 			return -EFAULT;
-		if ((tstimes[0].tv_nsec == UTIME_OMIT ||
-		     tstimes[0].tv_nsec == UTIME_NOW) &&
-		    tstimes[0].tv_sec != 0)
-			return -EINVAL;
-		if ((tstimes[1].tv_nsec == UTIME_OMIT ||
-		     tstimes[1].tv_nsec == UTIME_NOW) &&
-		    tstimes[1].tv_sec != 0)
-			return -EINVAL;

 		/* Nothing to do, we must not even check the path.  */
 		if (tstimes[0].tv_nsec == UTIME_OMIT &&





       reply	other threads:[~2008-06-03 20:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <48454F1D.6060507@gmail.com>
2008-06-03 20:13 ` Michael Kerrisk [this message]
2008-06-03 20:22   ` utimensat() non-conformances and fixes [v4] (patch) Andrew Morton
2008-06-03 20:29     ` Michael Kerrisk
2008-06-03 20:14 ` utimensat() non-conformances and fixes [v4] (test suite) Michael Kerrisk
     [not found] ` <484569E5.5090108@gmail.com>
2008-06-03 20:15   ` utimensat() non-conformances and fixes [v4] (test results) Michael Kerrisk

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=4845A606.6070005@gmail.com \
    --to=mtk.manpages@googlemail.com \
    --cc=akpm@linux-foundation.org \
    --cc=drepper@redhat.com \
    --cc=hch@lst.de \
    --cc=jamie@shareable.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=mtk.manpages@gmail.com \
    --cc=subrata@linux.vnet.ibm.com \
    --cc=viro@zeniv.linux.org.uk \
    /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;
as well as URLs for NNTP newsgroup(s).