diff options
Diffstat (limited to 'fs/cifs/xattr.c')
-rw-r--r-- | fs/cifs/xattr.c | 143 |
1 files changed, 93 insertions, 50 deletions
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a1509207bfa6..2a22fb2989e4 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -30,10 +30,11 @@ | |||
30 | 30 | ||
31 | #define MAX_EA_VALUE_SIZE 65535 | 31 | #define MAX_EA_VALUE_SIZE 65535 |
32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" | 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" |
33 | #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" | ||
33 | #define CIFS_XATTR_USER_PREFIX "user." | 34 | #define CIFS_XATTR_USER_PREFIX "user." |
34 | #define CIFS_XATTR_SYSTEM_PREFIX "system." | 35 | #define CIFS_XATTR_SYSTEM_PREFIX "system." |
35 | #define CIFS_XATTR_OS2_PREFIX "os2." | 36 | #define CIFS_XATTR_OS2_PREFIX "os2." |
36 | #define CIFS_XATTR_SECURITY_PREFIX ".security" | 37 | #define CIFS_XATTR_SECURITY_PREFIX "security." |
37 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." | 38 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." |
38 | #define XATTR_TRUSTED_PREFIX_LEN 8 | 39 | #define XATTR_TRUSTED_PREFIX_LEN 8 |
39 | #define XATTR_SECURITY_PREFIX_LEN 9 | 40 | #define XATTR_SECURITY_PREFIX_LEN 9 |
@@ -47,9 +48,10 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
47 | #ifdef CONFIG_CIFS_XATTR | 48 | #ifdef CONFIG_CIFS_XATTR |
48 | int xid; | 49 | int xid; |
49 | struct cifs_sb_info *cifs_sb; | 50 | struct cifs_sb_info *cifs_sb; |
50 | struct cifsTconInfo *pTcon; | 51 | struct tcon_link *tlink; |
52 | struct cifs_tcon *pTcon; | ||
51 | struct super_block *sb; | 53 | struct super_block *sb; |
52 | char *full_path; | 54 | char *full_path = NULL; |
53 | 55 | ||
54 | if (direntry == NULL) | 56 | if (direntry == NULL) |
55 | return -EIO; | 57 | return -EIO; |
@@ -58,16 +60,19 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
58 | sb = direntry->d_inode->i_sb; | 60 | sb = direntry->d_inode->i_sb; |
59 | if (sb == NULL) | 61 | if (sb == NULL) |
60 | return -EIO; | 62 | return -EIO; |
61 | xid = GetXid(); | ||
62 | 63 | ||
63 | cifs_sb = CIFS_SB(sb); | 64 | cifs_sb = CIFS_SB(sb); |
64 | pTcon = cifs_sb->tcon; | 65 | tlink = cifs_sb_tlink(cifs_sb); |
66 | if (IS_ERR(tlink)) | ||
67 | return PTR_ERR(tlink); | ||
68 | pTcon = tlink_tcon(tlink); | ||
69 | |||
70 | xid = GetXid(); | ||
65 | 71 | ||
66 | full_path = build_path_from_dentry(direntry); | 72 | full_path = build_path_from_dentry(direntry); |
67 | if (full_path == NULL) { | 73 | if (full_path == NULL) { |
68 | rc = -ENOMEM; | 74 | rc = -ENOMEM; |
69 | FreeXid(xid); | 75 | goto remove_ea_exit; |
70 | return rc; | ||
71 | } | 76 | } |
72 | if (ea_name == NULL) { | 77 | if (ea_name == NULL) { |
73 | cFYI(1, "Null xattr names not supported"); | 78 | cFYI(1, "Null xattr names not supported"); |
@@ -91,6 +96,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
91 | remove_ea_exit: | 96 | remove_ea_exit: |
92 | kfree(full_path); | 97 | kfree(full_path); |
93 | FreeXid(xid); | 98 | FreeXid(xid); |
99 | cifs_put_tlink(tlink); | ||
94 | #endif | 100 | #endif |
95 | return rc; | 101 | return rc; |
96 | } | 102 | } |
@@ -102,9 +108,11 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
102 | #ifdef CONFIG_CIFS_XATTR | 108 | #ifdef CONFIG_CIFS_XATTR |
103 | int xid; | 109 | int xid; |
104 | struct cifs_sb_info *cifs_sb; | 110 | struct cifs_sb_info *cifs_sb; |
105 | struct cifsTconInfo *pTcon; | 111 | struct tcon_link *tlink; |
112 | struct cifs_tcon *pTcon; | ||
106 | struct super_block *sb; | 113 | struct super_block *sb; |
107 | char *full_path; | 114 | char *full_path; |
115 | struct cifs_ntsd *pacl; | ||
108 | 116 | ||
109 | if (direntry == NULL) | 117 | if (direntry == NULL) |
110 | return -EIO; | 118 | return -EIO; |
@@ -113,16 +121,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
113 | sb = direntry->d_inode->i_sb; | 121 | sb = direntry->d_inode->i_sb; |
114 | if (sb == NULL) | 122 | if (sb == NULL) |
115 | return -EIO; | 123 | return -EIO; |
116 | xid = GetXid(); | ||
117 | 124 | ||
118 | cifs_sb = CIFS_SB(sb); | 125 | cifs_sb = CIFS_SB(sb); |
119 | pTcon = cifs_sb->tcon; | 126 | tlink = cifs_sb_tlink(cifs_sb); |
127 | if (IS_ERR(tlink)) | ||
128 | return PTR_ERR(tlink); | ||
129 | pTcon = tlink_tcon(tlink); | ||
130 | |||
131 | xid = GetXid(); | ||
120 | 132 | ||
121 | full_path = build_path_from_dentry(direntry); | 133 | full_path = build_path_from_dentry(direntry); |
122 | if (full_path == NULL) { | 134 | if (full_path == NULL) { |
123 | rc = -ENOMEM; | 135 | rc = -ENOMEM; |
124 | FreeXid(xid); | 136 | goto set_ea_exit; |
125 | return rc; | ||
126 | } | 137 | } |
127 | /* return dos attributes as pseudo xattr */ | 138 | /* return dos attributes as pseudo xattr */ |
128 | /* return alt name if available as pseudo attr */ | 139 | /* return alt name if available as pseudo attr */ |
@@ -132,9 +143,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
132 | returns as xattrs */ | 143 | returns as xattrs */ |
133 | if (value_size > MAX_EA_VALUE_SIZE) { | 144 | if (value_size > MAX_EA_VALUE_SIZE) { |
134 | cFYI(1, "size of EA value too large"); | 145 | cFYI(1, "size of EA value too large"); |
135 | kfree(full_path); | 146 | rc = -EOPNOTSUPP; |
136 | FreeXid(xid); | 147 | goto set_ea_exit; |
137 | return -EOPNOTSUPP; | ||
138 | } | 148 | } |
139 | 149 | ||
140 | if (ea_name == NULL) { | 150 | if (ea_name == NULL) { |
@@ -157,6 +167,25 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
157 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 167 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, |
158 | (__u16)value_size, cifs_sb->local_nls, | 168 | (__u16)value_size, cifs_sb->local_nls, |
159 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 169 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
172 | pacl = kmalloc(value_size, GFP_KERNEL); | ||
173 | if (!pacl) { | ||
174 | cFYI(1, "%s: Can't allocate memory for ACL", | ||
175 | __func__); | ||
176 | rc = -ENOMEM; | ||
177 | } else { | ||
178 | #ifdef CONFIG_CIFS_ACL | ||
179 | memcpy(pacl, ea_value, value_size); | ||
180 | rc = set_cifs_acl(pacl, value_size, | ||
181 | direntry->d_inode, full_path); | ||
182 | if (rc == 0) /* force revalidate of the inode */ | ||
183 | CIFS_I(direntry->d_inode)->time = 0; | ||
184 | kfree(pacl); | ||
185 | #else | ||
186 | cFYI(1, "Set CIFS ACL not supported yet"); | ||
187 | #endif /* CONFIG_CIFS_ACL */ | ||
188 | } | ||
160 | } else { | 189 | } else { |
161 | int temp; | 190 | int temp; |
162 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 191 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
@@ -198,6 +227,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
198 | set_ea_exit: | 227 | set_ea_exit: |
199 | kfree(full_path); | 228 | kfree(full_path); |
200 | FreeXid(xid); | 229 | FreeXid(xid); |
230 | cifs_put_tlink(tlink); | ||
201 | #endif | 231 | #endif |
202 | return rc; | 232 | return rc; |
203 | } | 233 | } |
@@ -209,7 +239,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
209 | #ifdef CONFIG_CIFS_XATTR | 239 | #ifdef CONFIG_CIFS_XATTR |
210 | int xid; | 240 | int xid; |
211 | struct cifs_sb_info *cifs_sb; | 241 | struct cifs_sb_info *cifs_sb; |
212 | struct cifsTconInfo *pTcon; | 242 | struct tcon_link *tlink; |
243 | struct cifs_tcon *pTcon; | ||
213 | struct super_block *sb; | 244 | struct super_block *sb; |
214 | char *full_path; | 245 | char *full_path; |
215 | 246 | ||
@@ -221,16 +252,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
221 | if (sb == NULL) | 252 | if (sb == NULL) |
222 | return -EIO; | 253 | return -EIO; |
223 | 254 | ||
224 | xid = GetXid(); | ||
225 | |||
226 | cifs_sb = CIFS_SB(sb); | 255 | cifs_sb = CIFS_SB(sb); |
227 | pTcon = cifs_sb->tcon; | 256 | tlink = cifs_sb_tlink(cifs_sb); |
257 | if (IS_ERR(tlink)) | ||
258 | return PTR_ERR(tlink); | ||
259 | pTcon = tlink_tcon(tlink); | ||
260 | |||
261 | xid = GetXid(); | ||
228 | 262 | ||
229 | full_path = build_path_from_dentry(direntry); | 263 | full_path = build_path_from_dentry(direntry); |
230 | if (full_path == NULL) { | 264 | if (full_path == NULL) { |
231 | rc = -ENOMEM; | 265 | rc = -ENOMEM; |
232 | FreeXid(xid); | 266 | goto get_ea_exit; |
233 | return rc; | ||
234 | } | 267 | } |
235 | /* return dos attributes as pseudo xattr */ | 268 | /* return dos attributes as pseudo xattr */ |
236 | /* return alt name if available as pseudo attr */ | 269 | /* return alt name if available as pseudo attr */ |
@@ -265,29 +298,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
265 | cifs_sb->local_nls, | 298 | cifs_sb->local_nls, |
266 | cifs_sb->mnt_cifs_flags & | 299 | cifs_sb->mnt_cifs_flags & |
267 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 300 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
268 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
269 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
270 | __u16 fid; | ||
271 | int oplock = 0; | ||
272 | struct cifs_ntsd *pacl = NULL; | ||
273 | __u32 buflen = 0; | ||
274 | if (experimEnabled) | ||
275 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
276 | FILE_OPEN, GENERIC_READ, 0, &fid, | ||
277 | &oplock, NULL, cifs_sb->local_nls, | ||
278 | cifs_sb->mnt_cifs_flags & | ||
279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
280 | /* else rc is EOPNOTSUPP from above */ | ||
281 | |||
282 | if (rc == 0) { | ||
283 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, | ||
284 | &buflen); | ||
285 | CIFSSMBClose(xid, pTcon, fid); | ||
286 | } | ||
287 | } | ||
288 | #endif /* EXPERIMENTAL */ | ||
289 | #else | 301 | #else |
290 | cFYI(1, "query POSIX ACL not supported yet"); | 302 | cFYI(1, "Query POSIX ACL not supported yet"); |
291 | #endif /* CONFIG_CIFS_POSIX */ | 303 | #endif /* CONFIG_CIFS_POSIX */ |
292 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 304 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, |
293 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 305 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { |
@@ -299,8 +311,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
299 | cifs_sb->mnt_cifs_flags & | 311 | cifs_sb->mnt_cifs_flags & |
300 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 312 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
301 | #else | 313 | #else |
302 | cFYI(1, "query POSIX default ACL not supported yet"); | 314 | cFYI(1, "Query POSIX default ACL not supported yet"); |
303 | #endif | 315 | #endif /* CONFIG_CIFS_POSIX */ |
316 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
317 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
318 | #ifdef CONFIG_CIFS_ACL | ||
319 | u32 acllen; | ||
320 | struct cifs_ntsd *pacl; | ||
321 | |||
322 | pacl = get_cifs_acl(cifs_sb, direntry->d_inode, | ||
323 | full_path, &acllen); | ||
324 | if (IS_ERR(pacl)) { | ||
325 | rc = PTR_ERR(pacl); | ||
326 | cERROR(1, "%s: error %zd getting sec desc", | ||
327 | __func__, rc); | ||
328 | } else { | ||
329 | if (ea_value) { | ||
330 | if (acllen > buf_size) | ||
331 | acllen = -ERANGE; | ||
332 | else | ||
333 | memcpy(ea_value, pacl, acllen); | ||
334 | } | ||
335 | rc = acllen; | ||
336 | kfree(pacl); | ||
337 | } | ||
338 | #else | ||
339 | cFYI(1, "Query CIFS ACL not supported yet"); | ||
340 | #endif /* CONFIG_CIFS_ACL */ | ||
304 | } else if (strncmp(ea_name, | 341 | } else if (strncmp(ea_name, |
305 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { | 342 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { |
306 | cFYI(1, "Trusted xattr namespace not supported yet"); | 343 | cFYI(1, "Trusted xattr namespace not supported yet"); |
@@ -323,6 +360,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
323 | get_ea_exit: | 360 | get_ea_exit: |
324 | kfree(full_path); | 361 | kfree(full_path); |
325 | FreeXid(xid); | 362 | FreeXid(xid); |
363 | cifs_put_tlink(tlink); | ||
326 | #endif | 364 | #endif |
327 | return rc; | 365 | return rc; |
328 | } | 366 | } |
@@ -333,7 +371,8 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
333 | #ifdef CONFIG_CIFS_XATTR | 371 | #ifdef CONFIG_CIFS_XATTR |
334 | int xid; | 372 | int xid; |
335 | struct cifs_sb_info *cifs_sb; | 373 | struct cifs_sb_info *cifs_sb; |
336 | struct cifsTconInfo *pTcon; | 374 | struct tcon_link *tlink; |
375 | struct cifs_tcon *pTcon; | ||
337 | struct super_block *sb; | 376 | struct super_block *sb; |
338 | char *full_path; | 377 | char *full_path; |
339 | 378 | ||
@@ -346,18 +385,20 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
346 | return -EIO; | 385 | return -EIO; |
347 | 386 | ||
348 | cifs_sb = CIFS_SB(sb); | 387 | cifs_sb = CIFS_SB(sb); |
349 | pTcon = cifs_sb->tcon; | ||
350 | |||
351 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 388 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
352 | return -EOPNOTSUPP; | 389 | return -EOPNOTSUPP; |
353 | 390 | ||
391 | tlink = cifs_sb_tlink(cifs_sb); | ||
392 | if (IS_ERR(tlink)) | ||
393 | return PTR_ERR(tlink); | ||
394 | pTcon = tlink_tcon(tlink); | ||
395 | |||
354 | xid = GetXid(); | 396 | xid = GetXid(); |
355 | 397 | ||
356 | full_path = build_path_from_dentry(direntry); | 398 | full_path = build_path_from_dentry(direntry); |
357 | if (full_path == NULL) { | 399 | if (full_path == NULL) { |
358 | rc = -ENOMEM; | 400 | rc = -ENOMEM; |
359 | FreeXid(xid); | 401 | goto list_ea_exit; |
360 | return rc; | ||
361 | } | 402 | } |
362 | /* return dos attributes as pseudo xattr */ | 403 | /* return dos attributes as pseudo xattr */ |
363 | /* return alt name if available as pseudo attr */ | 404 | /* return alt name if available as pseudo attr */ |
@@ -370,8 +411,10 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
370 | cifs_sb->mnt_cifs_flags & | 411 | cifs_sb->mnt_cifs_flags & |
371 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 412 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
372 | 413 | ||
414 | list_ea_exit: | ||
373 | kfree(full_path); | 415 | kfree(full_path); |
374 | FreeXid(xid); | 416 | FreeXid(xid); |
417 | cifs_put_tlink(tlink); | ||
375 | #endif | 418 | #endif |
376 | return rc; | 419 | return rc; |
377 | } | 420 | } |