Skip to content

Commit 8b6427a

Browse files
jtlaytonSteve French
authored andcommitted
cifs: fix pointer initialization and checks in cifs_follow_symlink (try #4)
This is the third respin of the patch posted yesterday to fix the error handling in cifs_follow_symlink. It also includes a fix for a bogus NULL pointer check in CIFSSMBQueryUnixSymLink that Jeff Moyer spotted. It's possible for CIFSSMBQueryUnixSymLink to return without setting target_path to a valid pointer. If that happens then the current value to which we're initializing this pointer could cause an oops when it's kfree'd. This patch is a little more comprehensive than the last patches. It reorganizes cifs_follow_link a bit for (hopefully) better readability. It should also eliminate the uneeded allocation of full_path on servers without unix extensions (assuming they can get to this point anyway, of which I'm not convinced). On a side note, I'm not sure I agree with the logic of enabling this query even when unix extensions are disabled on the client. It seems like that should disable this as well. But, changing that is outside the scope of this fix, so I've left it alone for now. Reported-by: Jeff Moyer <[email protected]> Signed-off-by: Jeff Layton <[email protected]> Reviewed-by: Jeff Moyer <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent b41a080 commit 8b6427a

File tree

2 files changed

+27
-27
lines changed

2 files changed

+27
-27
lines changed

fs/cifs/cifssmb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2475,7 +2475,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
24752475
/* BB FIXME investigate remapping reserved chars here */
24762476
*symlinkinfo = cifs_strndup_from_ucs(data_start, count,
24772477
is_unicode, nls_codepage);
2478-
if (!symlinkinfo)
2478+
if (!*symlinkinfo)
24792479
rc = -ENOMEM;
24802480
}
24812481
}

fs/cifs/link.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,48 +107,48 @@ void *
107107
cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
108108
{
109109
struct inode *inode = direntry->d_inode;
110-
int rc = -EACCES;
110+
int rc = -ENOMEM;
111111
int xid;
112112
char *full_path = NULL;
113-
char *target_path = ERR_PTR(-ENOMEM);
114-
struct cifs_sb_info *cifs_sb;
115-
struct cifsTconInfo *pTcon;
113+
char *target_path = NULL;
114+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
115+
struct cifsTconInfo *tcon = cifs_sb->tcon;
116116

117117
xid = GetXid();
118118

119-
full_path = build_path_from_dentry(direntry);
119+
/*
120+
* For now, we just handle symlinks with unix extensions enabled.
121+
* Eventually we should handle NTFS reparse points, and MacOS
122+
* symlink support. For instance...
123+
*
124+
* rc = CIFSSMBQueryReparseLinkInfo(...)
125+
*
126+
* For now, just return -EACCES when the server doesn't support posix
127+
* extensions. Note that we still allow querying symlinks when posix
128+
* extensions are manually disabled. We could disable these as well
129+
* but there doesn't seem to be any harm in allowing the client to
130+
* read them.
131+
*/
132+
if (!(tcon->ses->capabilities & CAP_UNIX)) {
133+
rc = -EACCES;
134+
goto out;
135+
}
120136

137+
full_path = build_path_from_dentry(direntry);
121138
if (!full_path)
122139
goto out;
123140

124141
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
125-
cifs_sb = CIFS_SB(inode->i_sb);
126-
pTcon = cifs_sb->tcon;
127-
128-
/* We could change this to:
129-
if (pTcon->unix_ext)
130-
but there does not seem any point in refusing to
131-
get symlink info if we can, even if unix extensions
132-
turned off for this mount */
133-
134-
if (pTcon->ses->capabilities & CAP_UNIX)
135-
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
136-
&target_path,
137-
cifs_sb->local_nls);
138-
else {
139-
/* BB add read reparse point symlink code here */
140-
/* rc = CIFSSMBQueryReparseLinkInfo */
141-
/* BB Add code to Query ReparsePoint info */
142-
/* BB Add MAC style xsymlink check here if enabled */
143-
}
144142

143+
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
144+
cifs_sb->local_nls);
145+
kfree(full_path);
146+
out:
145147
if (rc != 0) {
146148
kfree(target_path);
147149
target_path = ERR_PTR(rc);
148150
}
149151

150-
kfree(full_path);
151-
out:
152152
FreeXid(xid);
153153
nd_set_link(nd, target_path);
154154
return NULL;

0 commit comments

Comments
 (0)