}
struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
- const struct cifs_fid *cifsfid, u32 *pacllen)
+ const struct cifs_fid *cifsfid, u32 *pacllen,
+ u32 __maybe_unused unused)
{
struct cifs_ntsd *pntsd = NULL;
unsigned int xid;
/* Retrieve an ACL from the server */
struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct inode *inode, const char *path,
- u32 *pacllen)
+ u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct cifsFileInfo *open_file = NULL;
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
- pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
+ pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
cifsFileInfo_put(open_file);
return pntsd;
}
int rc = 0;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
struct smb_version_operations *ops;
+ const u32 info = 0;
cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
ops = tlink_tcon(tlink)->ses->server->ops;
if (pfid && (ops->get_acl_by_fid))
- pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
+ pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen, info);
else if (ops->get_acl)
- pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
+ pntsd = ops->get_acl(cifs_sb, inode, path, &acllen, info);
else {
cifs_put_tlink(tlink);
return -EOPNOTSUPP;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
struct smb_version_operations *ops;
bool mode_from_sid, id_from_sid;
+ const u32 info = 0;
if (IS_ERR(tlink))
return PTR_ERR(tlink);
return -EOPNOTSUPP;
}
- pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
+ pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen, info);
if (IS_ERR(pntsd)) {
rc = PTR_ERR(pntsd);
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
const char *, const void *, const __u16,
const struct nls_table *, struct cifs_sb_info *);
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
- const char *, u32 *);
+ const char *, u32 *, u32);
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
- const struct cifs_fid *, u32 *);
+ const struct cifs_fid *, u32 *, u32);
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
int);
/* writepages retry size */
#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
/* synchronize with the completion */
/* of an input/output request */
+#define SYSTEM_SECURITY 0x01000000 /* The system access control list */
+ /* can be read and changed */
#define GENERIC_ALL 0x10000000
#define GENERIC_EXECUTE 0x20000000
#define GENERIC_WRITE 0x40000000
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
kuid_t uid, kgid_t gid);
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
- const char *, u32 *);
+ const char *, u32 *, u32);
extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
- const struct cifs_fid *, u32 *);
+ const struct cifs_fid *, u32 *, u32);
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
const char *, int);
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
static struct cifs_ntsd *
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
- const struct cifs_fid *cifsfid, u32 *pacllen)
+ const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
unsigned int xid;
cifs_dbg(FYI, "trying to get acl\n");
rc = SMB2_query_acl(xid, tlink_tcon(tlink), cifsfid->persistent_fid,
- cifsfid->volatile_fid, (void **)&pntsd, pacllen);
+ cifsfid->volatile_fid, (void **)&pntsd, pacllen,
+ info);
free_xid(xid);
cifs_put_tlink(tlink);
static struct cifs_ntsd *
get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
- const char *path, u32 *pacllen)
+ const char *path, u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
oparms.fid = &fid;
oparms.reconnect = false;
+ if (info & SACL_SECINFO)
+ oparms.desired_access |= SYSTEM_SECURITY;
+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
NULL);
kfree(utf16_path);
if (!rc) {
rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
- fid.volatile_fid, (void **)&pntsd, pacllen);
+ fid.volatile_fid, (void **)&pntsd, pacllen,
+ info);
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
}
tcon = tlink_tcon(tlink);
xid = get_xid();
- if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
- access_flags = WRITE_OWNER;
- else
- access_flags = WRITE_DAC;
+ if (aclflag & CIFS_ACL_OWNER || aclflag & CIFS_ACL_GROUP)
+ access_flags |= WRITE_OWNER;
+ if (aclflag & CIFS_ACL_SACL)
+ access_flags |= SYSTEM_SECURITY;
+ if (aclflag & CIFS_ACL_DACL)
+ access_flags |= WRITE_DAC;
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
if (!utf16_path) {
/* Retrieve an ACL from the server */
static struct cifs_ntsd *
get_smb2_acl(struct cifs_sb_info *cifs_sb,
- struct inode *inode, const char *path,
- u32 *pacllen)
+ struct inode *inode, const char *path,
+ u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct cifsFileInfo *open_file = NULL;
if (inode)
open_file = find_readable_file(CIFS_I(inode), true);
if (!open_file)
- return get_smb2_acl_by_path(cifs_sb, path, pacllen);
+ return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
- pntsd = get_smb2_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
+ pntsd = get_smb2_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
cifsFileInfo_put(open_file);
return pntsd;
}
int
SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- void **data, u32 *plen)
+ u64 persistent_fid, u64 volatile_fid,
+ void **data, u32 *plen, u32 additional_info)
{
- __u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
*plen = 0;
return query_info(xid, tcon, persistent_fid, volatile_fid,
size_t input_len, void *input);
extern void SMB2_query_info_free(struct smb_rqst *rqst);
extern int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- void **data, unsigned int *plen);
+ u64 persistent_file_id, u64 volatile_file_id,
+ void **data, unsigned int *plen, u32 info);
extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
__le64 *uniqueid);
#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,
break;
case XATTR_CIFS_ACL:
- case XATTR_CIFS_NTSD: {
+ case XATTR_CIFS_NTSD:
+ case XATTR_CIFS_NTSD_FULL: {
struct cifs_ntsd *pacl;
if (!value)
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;
}
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, additional_info = 0;
struct cifs_ntsd *pacl;
if (pTcon->ses->server->ops->get_acl == NULL)
goto out; /* rc already EOPNOTSUPP */
+ if (handler->flags == XATTR_CIFS_NTSD_FULL) {
+ additional_info = OWNER_SECINFO | GROUP_SECINFO |
+ DACL_SECINFO | SACL_SECINFO;
+ } else {
+ additional_info = OWNER_SECINFO | GROUP_SECINFO |
+ DACL_SECINFO;
+ }
pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
- inode, full_path, &acllen);
+ inode, full_path, &acllen, additional_info);
if (IS_ERR(pacl)) {
rc = PTR_ERR(pacl);
cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
.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,
&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