cifs: fix dfs-links
[sfrench/cifs-2.6.git] / fs / cifs / xattr.c
index b8299173ea7e3c3db0439490d9ae616c72540281..6b658a1172ef00e1ec5ff7c40435346561e3e290 100644 (file)
@@ -34,6 +34,7 @@
 #define MAX_EA_VALUE_SIZE CIFSMaxBufSize
 #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
 #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
+#define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
 #define CIFS_XATTR_ATTRIB "cifs.dosattrib"  /* full name: user.cifs.dosattrib */
 #define CIFS_XATTR_CREATETIME "cifs.creationtime"  /* user.cifs.creationtime */
 /*
  */
 #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
 #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
+#define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
 #define SMB3_XATTR_ATTRIB "smb3.dosattrib"  /* full name: user.smb3.dosattrib */
 #define SMB3_XATTR_CREATETIME "smb3.creationtime"  /* user.smb3.creationtime */
 /* BB need to add server (Samba e.g) support for security and trusted prefix */
 
 enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
-       XATTR_CIFS_NTSD };
+       XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
 
 static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
                           struct inode *inode, char *full_path,
@@ -164,7 +166,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
                break;
 
        case XATTR_CIFS_ACL:
-       case XATTR_CIFS_NTSD: {
+       case XATTR_CIFS_NTSD:
+       case XATTR_CIFS_NTSD_FULL: {
                struct cifs_ntsd *pacl;
 
                if (!value)
@@ -174,23 +177,27 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
                        rc = -ENOMEM;
                } else {
                        memcpy(pacl, value, size);
-                       if (value &&
-                           pTcon->ses->server->ops->set_acl) {
+                       if (pTcon->ses->server->ops->set_acl) {
+                               int aclflags = 0;
                                rc = 0;
-                               if (handler->flags == XATTR_CIFS_NTSD) {
-                                       /* set owner and DACL */
-                                       rc = pTcon->ses->server->ops->set_acl(
-                                                       pacl, size, inode,
-                                                       full_path,
-                                                       CIFS_ACL_OWNER);
-                               }
-                               if (rc == 0) {
-                                       /* set DACL */
-                                       rc = pTcon->ses->server->ops->set_acl(
-                                                       pacl, size, inode,
-                                                       full_path,
-                                                       CIFS_ACL_DACL);
+
+                               switch (handler->flags) {
+                               case XATTR_CIFS_NTSD_FULL:
+                                       aclflags = (CIFS_ACL_OWNER |
+                                                   CIFS_ACL_DACL |
+                                                   CIFS_ACL_SACL);
+                                       break;
+                               case XATTR_CIFS_NTSD:
+                                       aclflags = (CIFS_ACL_OWNER |
+                                                   CIFS_ACL_DACL);
+                                       break;
+                               case XATTR_CIFS_ACL:
+                               default:
+                                       aclflags = CIFS_ACL_DACL;
                                }
+
+                               rc = pTcon->ses->server->ops->set_acl(pacl,
+                                       size, inode, full_path, aclflags);
                        } else {
                                rc = -EOPNOTSUPP;
                        }
@@ -327,16 +334,25 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
                break;
 
        case XATTR_CIFS_ACL:
-       case XATTR_CIFS_NTSD: {
-               /* the whole ntsd is fetched regardless */
-               u32 acllen;
+       case XATTR_CIFS_NTSD:
+       case XATTR_CIFS_NTSD_FULL: {
+               /*
+                * fetch owner, DACL, and SACL if asked for full descriptor,
+                * fetch owner and DACL otherwise
+                */
+               u32 acllen, extra_info;
                struct cifs_ntsd *pacl;
 
                if (pTcon->ses->server->ops->get_acl == NULL)
                        goto out; /* rc already EOPNOTSUPP */
 
+               if (handler->flags == XATTR_CIFS_NTSD_FULL) {
+                       extra_info = SACL_SECINFO;
+               } else {
+                       extra_info = 0;
+               }
                pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
-                               inode, full_path, &acllen);
+                               inode, full_path, &acllen, extra_info);
                if (IS_ERR(pacl)) {
                        rc = PTR_ERR(pacl);
                        cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
@@ -486,6 +502,27 @@ static const struct xattr_handler smb3_ntsd_xattr_handler = {
        .set = cifs_xattr_set,
 };
 
+static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
+       .name = CIFS_XATTR_CIFS_NTSD_FULL,
+       .flags = XATTR_CIFS_NTSD_FULL,
+       .get = cifs_xattr_get,
+       .set = cifs_xattr_set,
+};
+
+/*
+ * Although this is just an alias for the above, need to move away from
+ * confusing users and using the 20 year old term 'cifs' when it is no
+ * longer secure and was replaced by SMB2/SMB3 a long time ago, and
+ * SMB3 and later are highly secure.
+ */
+static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
+       .name = SMB3_XATTR_CIFS_NTSD_FULL,
+       .flags = XATTR_CIFS_NTSD_FULL,
+       .get = cifs_xattr_get,
+       .set = cifs_xattr_set,
+};
+
+
 static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
        .name = XATTR_NAME_POSIX_ACL_ACCESS,
        .flags = XATTR_ACL_ACCESS,
@@ -507,6 +544,8 @@ const struct xattr_handler *cifs_xattr_handlers[] = {
        &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
        &cifs_cifs_ntsd_xattr_handler,
        &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
+       &cifs_cifs_ntsd_full_xattr_handler,
+       &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
        &cifs_posix_acl_access_xattr_handler,
        &cifs_posix_acl_default_xattr_handler,
        NULL