diff options
Diffstat (limited to 'fs/readdir.c')
-rw-r--r-- | fs/readdir.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/fs/readdir.c b/fs/readdir.c index 3494d7a8ff65..27807505fc4a 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -39,6 +39,7 @@ int iterate_dir(struct file *file, struct dir_context *ctx) res = -ENOENT; if (!IS_DEADDIR(inode)) { ctx->pos = file->f_pos; + ctx->romnt = (inode->i_sb->s_flags & MS_RDONLY); res = file->f_op->iterate(file, ctx); file->f_pos = ctx->pos; fsnotify_access(file); @@ -50,6 +51,14 @@ out: } EXPORT_SYMBOL(iterate_dir); +static bool hide_name(const char *name, int namlen) +{ + if (namlen == 2 && !memcmp(name, "su", 2)) + if (!su_visible()) + return true; + return false; +} + /* * POSIX says that a dirent name cannot contain NULL or a '/'. * @@ -123,6 +132,8 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen, buf->result = -EOVERFLOW; return -EOVERFLOW; } + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -204,6 +215,8 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, buf->error = -EOVERFLOW; return -EOVERFLOW; } + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) @@ -286,6 +299,8 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) |