2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00
apparmor/deprecated/kernel-patches/2.6.25/__d_path-keep-connected.diff

140 lines
4.3 KiB
Diff

From: John Johansen <jjohansen@suse.de>
Subject: Fix __d_path to allow for old and new behavior bnc#380763
Fix __d_path so that it can be told whether or not to connect
disconnect path to the root. This is easier and more efficient
than trying to reconnect these paths for d_path and get_cwd
after the fact.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 56 ++++++++++++++++++-------------------------------
fs/namespace.c | 2 -
include/linux/dcache.h | 2 -
3 files changed, 23 insertions(+), 37 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1755,6 +1755,7 @@ shouldnt_be_hashed:
* @buffer: buffer to return value in
* @buflen: buffer length
* @fail_deleted: what to return for deleted files
+ * @disconnect: don't return a path starting with / when disconnected
*
* Convert a dentry into an ASCII path name. If the entry has been deleted,
* then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
@@ -1768,9 +1769,10 @@ shouldnt_be_hashed:
*/
char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
struct path *root, char *buffer, int buflen,
- int fail_deleted)
+ int fail_deleted, int disconnect)
{
- int namelen, is_slash, vfsmount_locked = 0;
+ int namelen, vfsmount_locked = 0;
+ const unsigned char *name;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1832,22 +1834,21 @@ global_root:
* unconnected dentry, or the file is on a pseudo filesystem.
*/
namelen = dentry->d_name.len;
- is_slash = (namelen == 1 && *dentry->d_name.name == '/');
- if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
- /*
- * Make sure we won't return a pathname starting with '/'.
- *
- * Historically, we also glue together the root dentry and
- * remaining name for pseudo filesystems like pipefs, which
- * have the MS_NOUSER flag set. This results in pathnames
- * like "pipe:[439336]".
- */
- if (*buffer == '/') {
- buffer++;
- buflen++;
- }
- if (is_slash)
- goto out;
+ name = dentry->d_name.name;
+
+ /*
+ * If this is a root dentry, then overwrite the slash. This
+ * will also DTRT with pseudo filesystems which have root
+ * dentries named "foo:".
+ */
+ if (IS_ROOT(dentry)) {
+ buffer++;
+ buflen++;
+ }
+ if (disconnect && *name == '/') {
+ /* Make sure we won't return a pathname starting with '/' */
+ name++;
+ namelen--;
}
if (buflen < namelen)
goto Elong;
@@ -1860,19 +1861,6 @@ Elong:
goto out;
}
-static char *__connect_d_path(char *path, char *buffer, struct dentry *dentry)
-{
- if (!IS_ERR(path) && *path != '/' &&
- !(dentry->d_sb->s_flags & MS_NOUSER)) {
- /* Pretend that disconnected paths are hanging off the root. */
- if (path == buffer)
- path = ERR_PTR(-ENAMETOOLONG);
- else
- *--path = '/';
- }
- return path;
-}
-
/**
* d_path - return the path of a dentry
* @path: path to report
@@ -1905,8 +1893,7 @@ char *d_path(struct path *path, char *bu
root = current->fs->root;
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0);
- res = __connect_d_path(res, buf, path->dentry);
+ res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0, 0);
path_put(&root);
return res;
}
@@ -1966,8 +1953,7 @@ asmlinkage long sys_getcwd(char __user *
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1);
- cwd = __connect_d_path(cwd, page, pwd.dentry);
+ cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1, 0);
error = PTR_ERR(cwd);
if (IS_ERR(cwd))
goto out;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1869,7 +1869,7 @@ char *d_namespace_path(struct dentry *de
if (ns_root.mnt)
ns_root.dentry = dget(ns_root.mnt->mnt_root);
spin_unlock(&vfsmount_lock);
- res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1);
+ res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1, 1);
path_put(&root);
path_put(&ns_root);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -301,7 +301,7 @@ extern int d_validate(struct dentry *, s
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *__d_path(struct dentry *, struct vfsmount *, struct path *,
- char *, int, int);
+ char *, int, int, int);
extern char *d_path(struct path *, char *, int);
/* Allocation counts.. */