Skip to content

Commit 1175b6b

Browse files
rhvgoyalMiklos Szeredi
authored andcommitted
ovl: do operations on underlying file system in mounter's context
Given we are now doing checks both on overlay inode as well underlying inode, we should be able to do checks and operations on underlying file system using mounter's context. So modify all operations to do checks/operations on underlying dentry/inode in the context of mounter. Signed-off-by: Vivek Goyal <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent c0ca3d7 commit 1175b6b

File tree

2 files changed

+72
-37
lines changed

2 files changed

+72
-37
lines changed

fs/overlayfs/dir.c

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,12 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
138138
int err;
139139
enum ovl_path_type type;
140140
struct path realpath;
141+
const struct cred *old_cred;
141142

142143
type = ovl_path_real(dentry, &realpath);
144+
old_cred = ovl_override_creds(dentry->d_sb);
143145
err = vfs_getattr(&realpath, stat);
146+
revert_creds(old_cred);
144147
if (err)
145148
return err;
146149

@@ -391,6 +394,8 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
391394
{
392395
int err;
393396
struct inode *inode;
397+
const struct cred *old_cred;
398+
struct cred *override_cred;
394399
struct kstat stat = {
395400
.mode = mode,
396401
.rdev = rdev,
@@ -405,28 +410,23 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
405410
if (err)
406411
goto out_iput;
407412

408-
if (!ovl_dentry_is_opaque(dentry)) {
409-
err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
410-
} else {
411-
const struct cred *old_cred;
412-
struct cred *override_cred;
413-
414-
old_cred = ovl_override_creds(dentry->d_sb);
415-
416-
err = -ENOMEM;
417-
override_cred = prepare_creds();
418-
if (override_cred) {
419-
override_cred->fsuid = old_cred->fsuid;
420-
override_cred->fsgid = old_cred->fsgid;
421-
put_cred(override_creds(override_cred));
422-
put_cred(override_cred);
423-
413+
old_cred = ovl_override_creds(dentry->d_sb);
414+
err = -ENOMEM;
415+
override_cred = prepare_creds();
416+
if (override_cred) {
417+
override_cred->fsuid = old_cred->fsuid;
418+
override_cred->fsgid = old_cred->fsgid;
419+
put_cred(override_creds(override_cred));
420+
put_cred(override_cred);
421+
422+
if (!ovl_dentry_is_opaque(dentry))
423+
err = ovl_create_upper(dentry, inode, &stat, link,
424+
hardlink);
425+
else
424426
err = ovl_create_over_whiteout(dentry, inode, &stat,
425-
link, hardlink);
426-
}
427-
revert_creds(old_cred);
427+
link, hardlink);
428428
}
429-
429+
revert_creds(old_cred);
430430
if (!err)
431431
inode = NULL;
432432
out_iput:
@@ -637,6 +637,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
637637
{
638638
enum ovl_path_type type;
639639
int err;
640+
const struct cred *old_cred;
641+
640642

641643
err = ovl_check_sticky(dentry);
642644
if (err)
@@ -651,15 +653,13 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
651653
goto out_drop_write;
652654

653655
type = ovl_path_type(dentry);
654-
if (OVL_TYPE_PURE_UPPER(type)) {
655-
err = ovl_remove_upper(dentry, is_dir);
656-
} else {
657-
const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
658656

657+
old_cred = ovl_override_creds(dentry->d_sb);
658+
if (OVL_TYPE_PURE_UPPER(type))
659+
err = ovl_remove_upper(dentry, is_dir);
660+
else
659661
err = ovl_remove_and_whiteout(dentry, is_dir);
660-
661-
revert_creds(old_cred);
662-
}
662+
revert_creds(old_cred);
663663
out_drop_write:
664664
ovl_drop_write(dentry);
665665
out:
@@ -764,8 +764,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
764764
old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
765765
new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
766766

767-
if (old_opaque || new_opaque)
768-
old_cred = ovl_override_creds(old->d_sb);
767+
old_cred = ovl_override_creds(old->d_sb);
769768

770769
if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
771770
opaquedir = ovl_check_empty_and_clear(new);
@@ -895,8 +894,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
895894
out_unlock:
896895
unlock_rename(new_upperdir, old_upperdir);
897896
out_revert_creds:
898-
if (old_opaque || new_opaque)
899-
revert_creds(old_cred);
897+
revert_creds(old_cred);
900898
out_drop_write:
901899
ovl_drop_write(old);
902900
out:

fs/overlayfs/inode.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
4141
{
4242
int err;
4343
struct dentry *upperdentry;
44+
const struct cred *old_cred;
4445

4546
/*
4647
* Check for permissions before trying to copy-up. This is redundant
@@ -84,7 +85,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
8485
attr->ia_valid &= ~ATTR_MODE;
8586

8687
inode_lock(upperdentry->d_inode);
88+
old_cred = ovl_override_creds(dentry->d_sb);
8789
err = notify_change(upperdentry, attr, NULL);
90+
revert_creds(old_cred);
8891
if (!err)
8992
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
9093
inode_unlock(upperdentry->d_inode);
@@ -102,9 +105,14 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
102105
struct kstat *stat)
103106
{
104107
struct path realpath;
108+
const struct cred *old_cred;
109+
int err;
105110

106111
ovl_path_real(dentry, &realpath);
107-
return vfs_getattr(&realpath, stat);
112+
old_cred = ovl_override_creds(dentry->d_sb);
113+
err = vfs_getattr(&realpath, stat);
114+
revert_creds(old_cred);
115+
return err;
108116
}
109117

110118
int ovl_permission(struct inode *inode, int mask)
@@ -188,6 +196,8 @@ static const char *ovl_get_link(struct dentry *dentry,
188196
{
189197
struct dentry *realdentry;
190198
struct inode *realinode;
199+
const struct cred *old_cred;
200+
const char *p;
191201

192202
if (!dentry)
193203
return ERR_PTR(-ECHILD);
@@ -198,13 +208,18 @@ static const char *ovl_get_link(struct dentry *dentry,
198208
if (WARN_ON(!realinode->i_op->get_link))
199209
return ERR_PTR(-EPERM);
200210

201-
return realinode->i_op->get_link(realdentry, realinode, done);
211+
old_cred = ovl_override_creds(dentry->d_sb);
212+
p = realinode->i_op->get_link(realdentry, realinode, done);
213+
revert_creds(old_cred);
214+
return p;
202215
}
203216

204217
static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
205218
{
206219
struct path realpath;
207220
struct inode *realinode;
221+
const struct cred *old_cred;
222+
int err;
208223

209224
ovl_path_real(dentry, &realpath);
210225
realinode = realpath.dentry->d_inode;
@@ -214,10 +229,12 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
214229

215230
touch_atime(&realpath);
216231

217-
return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
232+
old_cred = ovl_override_creds(dentry->d_sb);
233+
err = realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
234+
revert_creds(old_cred);
235+
return err;
218236
}
219237

220-
221238
static bool ovl_is_private_xattr(const char *name)
222239
{
223240
return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
@@ -229,6 +246,7 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
229246
{
230247
int err;
231248
struct dentry *upperdentry;
249+
const struct cred *old_cred;
232250

233251
err = ovl_want_write(dentry);
234252
if (err)
@@ -243,7 +261,9 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
243261
goto out_drop_write;
244262

245263
upperdentry = ovl_dentry_upper(dentry);
264+
old_cred = ovl_override_creds(dentry->d_sb);
246265
err = vfs_setxattr(upperdentry, name, value, size, flags);
266+
revert_creds(old_cred);
247267

248268
out_drop_write:
249269
ovl_drop_write(dentry);
@@ -255,20 +275,28 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
255275
const char *name, void *value, size_t size)
256276
{
257277
struct dentry *realdentry = ovl_dentry_real(dentry);
278+
ssize_t res;
279+
const struct cred *old_cred;
258280

259281
if (ovl_is_private_xattr(name))
260282
return -ENODATA;
261283

262-
return vfs_getxattr(realdentry, name, value, size);
284+
old_cred = ovl_override_creds(dentry->d_sb);
285+
res = vfs_getxattr(realdentry, name, value, size);
286+
revert_creds(old_cred);
287+
return res;
263288
}
264289

265290
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
266291
{
267292
struct dentry *realdentry = ovl_dentry_real(dentry);
268293
ssize_t res;
269294
int off;
295+
const struct cred *old_cred;
270296

297+
old_cred = ovl_override_creds(dentry->d_sb);
271298
res = vfs_listxattr(realdentry, list, size);
299+
revert_creds(old_cred);
272300
if (res <= 0 || size == 0)
273301
return res;
274302

@@ -295,6 +323,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
295323
int err;
296324
struct path realpath;
297325
enum ovl_path_type type = ovl_path_real(dentry, &realpath);
326+
const struct cred *old_cred;
298327

299328
err = ovl_want_write(dentry);
300329
if (err)
@@ -316,7 +345,9 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
316345
ovl_path_upper(dentry, &realpath);
317346
}
318347

348+
old_cred = ovl_override_creds(dentry->d_sb);
319349
err = vfs_removexattr(realpath.dentry, name);
350+
revert_creds(old_cred);
320351
out_drop_write:
321352
ovl_drop_write(dentry);
322353
out:
@@ -326,14 +357,20 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
326357
struct posix_acl *ovl_get_acl(struct inode *inode, int type)
327358
{
328359
struct inode *realinode = ovl_inode_real(inode);
360+
const struct cred *old_cred;
361+
struct posix_acl *acl;
329362

330363
if (!IS_POSIXACL(realinode))
331364
return NULL;
332365

333366
if (!realinode->i_op->get_acl)
334367
return NULL;
335368

336-
return realinode->i_op->get_acl(realinode, type);
369+
old_cred = ovl_override_creds(inode->i_sb);
370+
acl = realinode->i_op->get_acl(realinode, type);
371+
revert_creds(old_cred);
372+
373+
return acl;
337374
}
338375

339376
static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,

0 commit comments

Comments
 (0)