summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/attr.c15
-rw-r--r--fs/utimes.c17
-rw-r--r--include/linux/fs.h1
3 files changed, 17 insertions, 16 deletions
diff --git a/fs/attr.c b/fs/attr.c
index 42bb42bb3c72..3c42cab06b5d 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -202,6 +202,21 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
202 return -EPERM; 202 return -EPERM;
203 } 203 }
204 204
205 /*
206 * If utimes(2) and friends are called with times == NULL (or both
207 * times are UTIME_NOW), then we need to check for write permission
208 */
209 if (ia_valid & ATTR_TOUCH) {
210 if (IS_IMMUTABLE(inode))
211 return -EPERM;
212
213 if (!inode_owner_or_capable(inode)) {
214 error = inode_permission(inode, MAY_WRITE);
215 if (error)
216 return error;
217 }
218 }
219
205 if ((ia_valid & ATTR_MODE)) { 220 if ((ia_valid & ATTR_MODE)) {
206 umode_t amode = attr->ia_mode; 221 umode_t amode = attr->ia_mode;
207 /* Flag setting protected by i_mutex */ 222 /* Flag setting protected by i_mutex */
diff --git a/fs/utimes.c b/fs/utimes.c
index 794f5f5b1fb5..ba54b9e648c9 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -87,21 +87,7 @@ static int utimes_common(struct path *path, struct timespec *times)
87 */ 87 */
88 newattrs.ia_valid |= ATTR_TIMES_SET; 88 newattrs.ia_valid |= ATTR_TIMES_SET;
89 } else { 89 } else {
90 /* 90 newattrs.ia_valid |= ATTR_TOUCH;
91 * If times is NULL (or both times are UTIME_NOW),
92 * then we need to check permissions, because
93 * inode_change_ok() won't do it.
94 */
95 error = -EPERM;
96 if (IS_IMMUTABLE(inode))
97 goto mnt_drop_write_and_out;
98
99 error = -EACCES;
100 if (!inode_owner_or_capable(inode)) {
101 error = inode_permission(inode, MAY_WRITE);
102 if (error)
103 goto mnt_drop_write_and_out;
104 }
105 } 91 }
106retry_deleg: 92retry_deleg:
107 inode_lock(inode); 93 inode_lock(inode);
@@ -113,7 +99,6 @@ retry_deleg:
113 goto retry_deleg; 99 goto retry_deleg;
114 } 100 }
115 101
116mnt_drop_write_and_out:
117 mnt_drop_write(path->mnt); 102 mnt_drop_write(path->mnt);
118out: 103out:
119 return error; 104 return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 901e25d495cc..7c391366fb43 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -224,6 +224,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
224#define ATTR_KILL_PRIV (1 << 14) 224#define ATTR_KILL_PRIV (1 << 14)
225#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */ 225#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
226#define ATTR_TIMES_SET (1 << 16) 226#define ATTR_TIMES_SET (1 << 16)
227#define ATTR_TOUCH (1 << 17)
227 228
228/* 229/*
229 * Whiteout is represented by a char device. The following constants define the 230 * Whiteout is represented by a char device. The following constants define the