Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.11 414 lines 12 kB view raw
1/* 2 * fs/cifs/xattr.c 3 * 4 * Copyright (c) International Business Machines Corp., 2003, 2007 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 * This library is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as published 9 * by the Free Software Foundation; either version 2.1 of the License, or 10 * (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#include <linux/fs.h> 23#include <linux/posix_acl_xattr.h> 24#include <linux/slab.h> 25#include <linux/xattr.h> 26#include "cifsfs.h" 27#include "cifspdu.h" 28#include "cifsglob.h" 29#include "cifsproto.h" 30#include "cifs_debug.h" 31 32#define MAX_EA_VALUE_SIZE 65535 33#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" 34#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" 35 36/* BB need to add server (Samba e.g) support for security and trusted prefix */ 37 38int cifs_removexattr(struct dentry *direntry, const char *ea_name) 39{ 40 int rc = -EOPNOTSUPP; 41#ifdef CONFIG_CIFS_XATTR 42 unsigned int xid; 43 struct cifs_sb_info *cifs_sb; 44 struct tcon_link *tlink; 45 struct cifs_tcon *pTcon; 46 struct super_block *sb; 47 char *full_path = NULL; 48 49 if (direntry == NULL) 50 return -EIO; 51 if (direntry->d_inode == NULL) 52 return -EIO; 53 sb = direntry->d_inode->i_sb; 54 if (sb == NULL) 55 return -EIO; 56 57 cifs_sb = CIFS_SB(sb); 58 tlink = cifs_sb_tlink(cifs_sb); 59 if (IS_ERR(tlink)) 60 return PTR_ERR(tlink); 61 pTcon = tlink_tcon(tlink); 62 63 xid = get_xid(); 64 65 full_path = build_path_from_dentry(direntry); 66 if (full_path == NULL) { 67 rc = -ENOMEM; 68 goto remove_ea_exit; 69 } 70 if (ea_name == NULL) { 71 cifs_dbg(FYI, "Null xattr names not supported\n"); 72 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) 73 && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) { 74 cifs_dbg(FYI, 75 "illegal xattr request %s (only user namespace supported)\n", 76 ea_name); 77 /* BB what if no namespace prefix? */ 78 /* Should we just pass them to server, except for 79 system and perhaps security prefixes? */ 80 } else { 81 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 82 goto remove_ea_exit; 83 84 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 85 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, 86 (__u16)0, cifs_sb->local_nls, 87 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 88 } 89remove_ea_exit: 90 kfree(full_path); 91 free_xid(xid); 92 cifs_put_tlink(tlink); 93#endif 94 return rc; 95} 96 97int cifs_setxattr(struct dentry *direntry, const char *ea_name, 98 const void *ea_value, size_t value_size, int flags) 99{ 100 int rc = -EOPNOTSUPP; 101#ifdef CONFIG_CIFS_XATTR 102 unsigned int xid; 103 struct cifs_sb_info *cifs_sb; 104 struct tcon_link *tlink; 105 struct cifs_tcon *pTcon; 106 struct super_block *sb; 107 char *full_path; 108 109 if (direntry == NULL) 110 return -EIO; 111 if (direntry->d_inode == NULL) 112 return -EIO; 113 sb = direntry->d_inode->i_sb; 114 if (sb == NULL) 115 return -EIO; 116 117 cifs_sb = CIFS_SB(sb); 118 tlink = cifs_sb_tlink(cifs_sb); 119 if (IS_ERR(tlink)) 120 return PTR_ERR(tlink); 121 pTcon = tlink_tcon(tlink); 122 123 xid = get_xid(); 124 125 full_path = build_path_from_dentry(direntry); 126 if (full_path == NULL) { 127 rc = -ENOMEM; 128 goto set_ea_exit; 129 } 130 /* return dos attributes as pseudo xattr */ 131 /* return alt name if available as pseudo attr */ 132 133 /* if proc/fs/cifs/streamstoxattr is set then 134 search server for EAs or streams to 135 returns as xattrs */ 136 if (value_size > MAX_EA_VALUE_SIZE) { 137 cifs_dbg(FYI, "size of EA value too large\n"); 138 rc = -EOPNOTSUPP; 139 goto set_ea_exit; 140 } 141 142 if (ea_name == NULL) { 143 cifs_dbg(FYI, "Null xattr names not supported\n"); 144 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) 145 == 0) { 146 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 147 goto set_ea_exit; 148 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) 149 cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); 150 151 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 152 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 153 (__u16)value_size, cifs_sb->local_nls, 154 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 155 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) 156 == 0) { 157 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 158 goto set_ea_exit; 159 160 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ 161 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 162 (__u16)value_size, cifs_sb->local_nls, 163 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 164 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, 165 strlen(CIFS_XATTR_CIFS_ACL)) == 0) { 166#ifdef CONFIG_CIFS_ACL 167 struct cifs_ntsd *pacl; 168 pacl = kmalloc(value_size, GFP_KERNEL); 169 if (!pacl) { 170 rc = -ENOMEM; 171 } else { 172 memcpy(pacl, ea_value, value_size); 173 rc = set_cifs_acl(pacl, value_size, 174 direntry->d_inode, full_path, CIFS_ACL_DACL); 175 if (rc == 0) /* force revalidate of the inode */ 176 CIFS_I(direntry->d_inode)->time = 0; 177 kfree(pacl); 178 } 179#else 180 cifs_dbg(FYI, "Set CIFS ACL not supported yet\n"); 181#endif /* CONFIG_CIFS_ACL */ 182 } else { 183 int temp; 184 temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, 185 strlen(POSIX_ACL_XATTR_ACCESS)); 186 if (temp == 0) { 187#ifdef CONFIG_CIFS_POSIX 188 if (sb->s_flags & MS_POSIXACL) 189 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, 190 ea_value, (const int)value_size, 191 ACL_TYPE_ACCESS, cifs_sb->local_nls, 192 cifs_sb->mnt_cifs_flags & 193 CIFS_MOUNT_MAP_SPECIAL_CHR); 194 cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc); 195#else 196 cifs_dbg(FYI, "set POSIX ACL not supported\n"); 197#endif 198 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, 199 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 200#ifdef CONFIG_CIFS_POSIX 201 if (sb->s_flags & MS_POSIXACL) 202 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, 203 ea_value, (const int)value_size, 204 ACL_TYPE_DEFAULT, cifs_sb->local_nls, 205 cifs_sb->mnt_cifs_flags & 206 CIFS_MOUNT_MAP_SPECIAL_CHR); 207 cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc); 208#else 209 cifs_dbg(FYI, "set default POSIX ACL not supported\n"); 210#endif 211 } else { 212 cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n", 213 ea_name); 214 /* BB what if no namespace prefix? */ 215 /* Should we just pass them to server, except for 216 system and perhaps security prefixes? */ 217 } 218 } 219 220set_ea_exit: 221 kfree(full_path); 222 free_xid(xid); 223 cifs_put_tlink(tlink); 224#endif 225 return rc; 226} 227 228ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, 229 void *ea_value, size_t buf_size) 230{ 231 ssize_t rc = -EOPNOTSUPP; 232#ifdef CONFIG_CIFS_XATTR 233 unsigned int xid; 234 struct cifs_sb_info *cifs_sb; 235 struct tcon_link *tlink; 236 struct cifs_tcon *pTcon; 237 struct super_block *sb; 238 char *full_path; 239 240 if (direntry == NULL) 241 return -EIO; 242 if (direntry->d_inode == NULL) 243 return -EIO; 244 sb = direntry->d_inode->i_sb; 245 if (sb == NULL) 246 return -EIO; 247 248 cifs_sb = CIFS_SB(sb); 249 tlink = cifs_sb_tlink(cifs_sb); 250 if (IS_ERR(tlink)) 251 return PTR_ERR(tlink); 252 pTcon = tlink_tcon(tlink); 253 254 xid = get_xid(); 255 256 full_path = build_path_from_dentry(direntry); 257 if (full_path == NULL) { 258 rc = -ENOMEM; 259 goto get_ea_exit; 260 } 261 /* return dos attributes as pseudo xattr */ 262 /* return alt name if available as pseudo attr */ 263 if (ea_name == NULL) { 264 cifs_dbg(FYI, "Null xattr names not supported\n"); 265 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) 266 == 0) { 267 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 268 goto get_ea_exit; 269 270 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) { 271 cifs_dbg(FYI, "attempt to query cifs inode metadata\n"); 272 /* revalidate/getattr then populate from inode */ 273 } /* BB add else when above is implemented */ 274 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 275 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 276 buf_size, cifs_sb->local_nls, 277 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 278 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 279 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 280 goto get_ea_exit; 281 282 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ 283 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 284 buf_size, cifs_sb->local_nls, 285 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 286 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, 287 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 288#ifdef CONFIG_CIFS_POSIX 289 if (sb->s_flags & MS_POSIXACL) 290 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 291 ea_value, buf_size, ACL_TYPE_ACCESS, 292 cifs_sb->local_nls, 293 cifs_sb->mnt_cifs_flags & 294 CIFS_MOUNT_MAP_SPECIAL_CHR); 295#else 296 cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); 297#endif /* CONFIG_CIFS_POSIX */ 298 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, 299 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 300#ifdef CONFIG_CIFS_POSIX 301 if (sb->s_flags & MS_POSIXACL) 302 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 303 ea_value, buf_size, ACL_TYPE_DEFAULT, 304 cifs_sb->local_nls, 305 cifs_sb->mnt_cifs_flags & 306 CIFS_MOUNT_MAP_SPECIAL_CHR); 307#else 308 cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); 309#endif /* CONFIG_CIFS_POSIX */ 310 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, 311 strlen(CIFS_XATTR_CIFS_ACL)) == 0) { 312#ifdef CONFIG_CIFS_ACL 313 u32 acllen; 314 struct cifs_ntsd *pacl; 315 316 pacl = get_cifs_acl(cifs_sb, direntry->d_inode, 317 full_path, &acllen); 318 if (IS_ERR(pacl)) { 319 rc = PTR_ERR(pacl); 320 cifs_dbg(VFS, "%s: error %zd getting sec desc\n", 321 __func__, rc); 322 } else { 323 if (ea_value) { 324 if (acllen > buf_size) 325 acllen = -ERANGE; 326 else 327 memcpy(ea_value, pacl, acllen); 328 } 329 rc = acllen; 330 kfree(pacl); 331 } 332#else 333 cifs_dbg(FYI, "Query CIFS ACL not supported yet\n"); 334#endif /* CONFIG_CIFS_ACL */ 335 } else if (strncmp(ea_name, 336 XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { 337 cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n"); 338 } else if (strncmp(ea_name, 339 XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { 340 cifs_dbg(FYI, "Security xattr namespace not supported yet\n"); 341 } else 342 cifs_dbg(FYI, 343 "illegal xattr request %s (only user namespace supported)\n", 344 ea_name); 345 346 /* We could add an additional check for streams ie 347 if proc/fs/cifs/streamstoxattr is set then 348 search server for EAs or streams to 349 returns as xattrs */ 350 351 if (rc == -EINVAL) 352 rc = -EOPNOTSUPP; 353 354get_ea_exit: 355 kfree(full_path); 356 free_xid(xid); 357 cifs_put_tlink(tlink); 358#endif 359 return rc; 360} 361 362ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) 363{ 364 ssize_t rc = -EOPNOTSUPP; 365#ifdef CONFIG_CIFS_XATTR 366 unsigned int xid; 367 struct cifs_sb_info *cifs_sb; 368 struct tcon_link *tlink; 369 struct cifs_tcon *pTcon; 370 struct super_block *sb; 371 char *full_path; 372 373 if (direntry == NULL) 374 return -EIO; 375 if (direntry->d_inode == NULL) 376 return -EIO; 377 sb = direntry->d_inode->i_sb; 378 if (sb == NULL) 379 return -EIO; 380 381 cifs_sb = CIFS_SB(sb); 382 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 383 return -EOPNOTSUPP; 384 385 tlink = cifs_sb_tlink(cifs_sb); 386 if (IS_ERR(tlink)) 387 return PTR_ERR(tlink); 388 pTcon = tlink_tcon(tlink); 389 390 xid = get_xid(); 391 392 full_path = build_path_from_dentry(direntry); 393 if (full_path == NULL) { 394 rc = -ENOMEM; 395 goto list_ea_exit; 396 } 397 /* return dos attributes as pseudo xattr */ 398 /* return alt name if available as pseudo attr */ 399 400 /* if proc/fs/cifs/streamstoxattr is set then 401 search server for EAs or streams to 402 returns as xattrs */ 403 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, 404 buf_size, cifs_sb->local_nls, 405 cifs_sb->mnt_cifs_flags & 406 CIFS_MOUNT_MAP_SPECIAL_CHR); 407 408list_ea_exit: 409 kfree(full_path); 410 free_xid(xid); 411 cifs_put_tlink(tlink); 412#endif 413 return rc; 414}