[CIFS] Allow setting mode via cifs acl
Requires cifsacl mount flag to be on and CIFS_EXPERIMENTAL enabled CC: Shirish Pargaonkar <shirishp@us.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
@@ -5,6 +5,8 @@ Enable experimental Kerberos support. Return writebehind errors on flush
|
|||||||
and sync so that events like out of disk space get reported properly on
|
and sync so that events like out of disk space get reported properly on
|
||||||
cached files. Fix setxattr failure to certain Samba versions. Fix mount
|
cached files. Fix setxattr failure to certain Samba versions. Fix mount
|
||||||
of second share to disconnected server session (autoreconnect on this).
|
of second share to disconnected server session (autoreconnect on this).
|
||||||
|
Add ability to modify cifs acls for handling chmod (when mounted with
|
||||||
|
cifsacl flag).
|
||||||
|
|
||||||
Version 1.51
|
Version 1.51
|
||||||
------------
|
------------
|
||||||
|
@@ -129,6 +129,54 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
|
|||||||
return (1); /* sids compare/match */
|
return (1); /* sids compare/match */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* copy ntsd, owner sid, and group sid from a security descriptor to another */
|
||||||
|
static void copy_sec_desc(const struct cifs_ntsd *pntsd,
|
||||||
|
struct cifs_ntsd *pnntsd, __u32 sidsoffset)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
||||||
|
struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
||||||
|
|
||||||
|
/* copy security descriptor control portion */
|
||||||
|
pnntsd->revision = pntsd->revision;
|
||||||
|
pnntsd->type = pntsd->type;
|
||||||
|
pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
|
||||||
|
pnntsd->sacloffset = 0;
|
||||||
|
pnntsd->osidoffset = cpu_to_le32(sidsoffset);
|
||||||
|
pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
|
||||||
|
|
||||||
|
/* copy owner sid */
|
||||||
|
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||||
|
le32_to_cpu(pntsd->osidoffset));
|
||||||
|
nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
|
||||||
|
|
||||||
|
nowner_sid_ptr->revision = owner_sid_ptr->revision;
|
||||||
|
nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
|
||||||
|
|
||||||
|
/* copy group sid */
|
||||||
|
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||||
|
le32_to_cpu(pntsd->gsidoffset));
|
||||||
|
ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
|
||||||
|
sizeof(struct cifs_sid));
|
||||||
|
|
||||||
|
ngroup_sid_ptr->revision = group_sid_ptr->revision;
|
||||||
|
ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
ngroup_sid_ptr->sub_auth[i] =
|
||||||
|
cpu_to_le32(group_sid_ptr->sub_auth[i]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
change posix mode to reflect permissions
|
change posix mode to reflect permissions
|
||||||
pmode is the existing mode (we only want to overwrite part of this
|
pmode is the existing mode (we only want to overwrite part of this
|
||||||
@@ -220,6 +268,33 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __le16 fill_ace_for_sid(struct cifs_ace *pntace,
|
||||||
|
const struct cifs_sid *psid, __u64 nmode, umode_t bits)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
__u16 size = 0;
|
||||||
|
__u32 access_req = 0;
|
||||||
|
|
||||||
|
pntace->type = ACCESS_ALLOWED;
|
||||||
|
pntace->flags = 0x0;
|
||||||
|
mode_to_access_flags(nmode, bits, &access_req);
|
||||||
|
if (!access_req)
|
||||||
|
access_req = SET_MINIMUM_RIGHTS;
|
||||||
|
pntace->access_req = cpu_to_le32(access_req);
|
||||||
|
|
||||||
|
pntace->sid.revision = psid->revision;
|
||||||
|
pntace->sid.num_subauth = psid->num_subauth;
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
pntace->sid.authority[i] = psid->authority[i];
|
||||||
|
for (i = 0; i < psid->num_subauth; i++)
|
||||||
|
pntace->sid.sub_auth[i] = psid->sub_auth[i];
|
||||||
|
|
||||||
|
size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
|
||||||
|
pntace->size = cpu_to_le16(size);
|
||||||
|
|
||||||
|
return (size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
||||||
@@ -243,7 +318,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
|||||||
int i;
|
int i;
|
||||||
cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
|
cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
|
||||||
pace->sid.revision, pace->sid.num_subauth, pace->type,
|
pace->sid.revision, pace->sid.num_subauth, pace->type,
|
||||||
pace->flags, pace->size));
|
pace->flags, le16_to_cpu(pace->size)));
|
||||||
for (i = 0; i < num_subauth; ++i) {
|
for (i = 0; i < num_subauth; ++i) {
|
||||||
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
|
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
|
||||||
le32_to_cpu(pace->sid.sub_auth[i])));
|
le32_to_cpu(pace->sid.sub_auth[i])));
|
||||||
@@ -346,6 +421,28 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
|
||||||
|
struct cifs_sid *pgrpsid, __u64 nmode)
|
||||||
|
{
|
||||||
|
__le16 size = 0;
|
||||||
|
struct cifs_acl *pnndacl;
|
||||||
|
|
||||||
|
pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
|
||||||
|
|
||||||
|
size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
|
||||||
|
pownersid, nmode, S_IRWXU);
|
||||||
|
size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
|
||||||
|
pgrpsid, nmode, S_IRWXG);
|
||||||
|
size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
|
||||||
|
&sid_everyone, nmode, S_IRWXO);
|
||||||
|
|
||||||
|
pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
|
||||||
|
pndacl->num_aces = 3;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
|
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
|
||||||
{
|
{
|
||||||
/* BB need to add parm so we can store the SID BB */
|
/* BB need to add parm so we can store the SID BB */
|
||||||
@@ -432,6 +529,46 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert permission bits from mode to equivalent CIFS ACL */
|
||||||
|
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||||
|
int acl_len, struct inode *inode, __u64 nmode)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
__u32 dacloffset;
|
||||||
|
__u32 ndacloffset;
|
||||||
|
__u32 sidsoffset;
|
||||||
|
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
||||||
|
struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
|
||||||
|
struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
|
||||||
|
|
||||||
|
if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
|
||||||
|
return (-EIO);
|
||||||
|
|
||||||
|
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||||
|
le32_to_cpu(pntsd->osidoffset));
|
||||||
|
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||||
|
le32_to_cpu(pntsd->gsidoffset));
|
||||||
|
|
||||||
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
||||||
|
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
|
||||||
|
|
||||||
|
ndacloffset = sizeof(struct cifs_ntsd);
|
||||||
|
ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
|
||||||
|
ndacl_ptr->revision = dacl_ptr->revision;
|
||||||
|
ndacl_ptr->size = 0;
|
||||||
|
ndacl_ptr->num_aces = 0;
|
||||||
|
|
||||||
|
rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
|
||||||
|
|
||||||
|
sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
|
||||||
|
|
||||||
|
/* copy security descriptor control portion and owner and group sid */
|
||||||
|
copy_sec_desc(pntsd, pnntsd, sidsoffset);
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Retrieve an ACL from the server */
|
/* Retrieve an ACL from the server */
|
||||||
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
||||||
const char *path)
|
const char *path)
|
||||||
@@ -487,6 +624,64 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
|||||||
return pntsd;
|
return pntsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set an ACL on the server */
|
||||||
|
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||||
|
struct inode *inode, const char *path)
|
||||||
|
{
|
||||||
|
struct cifsFileInfo *open_file;
|
||||||
|
int unlock_file = FALSE;
|
||||||
|
int xid;
|
||||||
|
int rc = -EIO;
|
||||||
|
__u16 fid;
|
||||||
|
struct super_block *sb;
|
||||||
|
struct cifs_sb_info *cifs_sb;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!inode)
|
||||||
|
return (rc);
|
||||||
|
|
||||||
|
sb = inode->i_sb;
|
||||||
|
if (sb == NULL)
|
||||||
|
return (rc);
|
||||||
|
|
||||||
|
cifs_sb = CIFS_SB(sb);
|
||||||
|
xid = GetXid();
|
||||||
|
|
||||||
|
open_file = find_readable_file(CIFS_I(inode));
|
||||||
|
if (open_file) {
|
||||||
|
unlock_file = TRUE;
|
||||||
|
fid = open_file->netfid;
|
||||||
|
} else {
|
||||||
|
int oplock = FALSE;
|
||||||
|
/* open file */
|
||||||
|
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
|
||||||
|
WRITE_DAC, 0, &fid, &oplock, NULL,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
if (rc != 0) {
|
||||||
|
cERROR(1, ("Unable to open file to set ACL"));
|
||||||
|
FreeXid(xid);
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("SetCIFSACL rc = %d", rc));
|
||||||
|
#endif
|
||||||
|
if (unlock_file == TRUE)
|
||||||
|
atomic_dec(&open_file->wrtPending);
|
||||||
|
else
|
||||||
|
CIFSSMBClose(xid, cifs_sb->tcon, fid);
|
||||||
|
|
||||||
|
FreeXid(xid);
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
||||||
void acl_to_uid_mode(struct inode *inode, const char *path)
|
void acl_to_uid_mode(struct inode *inode, const char *path)
|
||||||
{
|
{
|
||||||
@@ -510,24 +705,53 @@ void acl_to_uid_mode(struct inode *inode, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Convert mode bits to an ACL so we can update the ACL on the server */
|
/* Convert mode bits to an ACL so we can update the ACL on the server */
|
||||||
int mode_to_acl(struct inode *inode, const char *path)
|
int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
__u32 acllen = 0;
|
__u32 acllen = 0;
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
|
||||||
|
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1, ("set ACL from mode for %s", path));
|
cFYI(1, ("set ACL from mode for %s", path));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Get the security descriptor */
|
/* Get the security descriptor */
|
||||||
pntsd = get_cifs_acl(&acllen, inode, path);
|
pntsd = get_cifs_acl(&acllen, inode, path);
|
||||||
|
|
||||||
/* Add/Modify the three ACEs for owner, group, everyone
|
/* Add three ACEs for owner, group, everyone getting rid of
|
||||||
while retaining the other ACEs */
|
other ACEs as chmod disables ACEs and set the security descriptor */
|
||||||
|
|
||||||
/* Set the security descriptor */
|
if (pntsd) {
|
||||||
|
/* allocate memory for the smb header,
|
||||||
|
set security descriptor request security descriptor
|
||||||
|
parameters, and secuirty descriptor itself */
|
||||||
|
|
||||||
|
pnntsd = kmalloc(acllen, GFP_KERNEL);
|
||||||
|
if (!pnntsd) {
|
||||||
|
cERROR(1, ("Unable to allocate security descriptor"));
|
||||||
|
kfree(pntsd);
|
||||||
|
return (-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
kfree(pntsd);
|
rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
|
||||||
return rc;
|
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("build_sec_desc rc: %d", rc));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!rc) {
|
||||||
|
/* Set the security descriptor */
|
||||||
|
rc = set_cifs_acl(pnntsd, acllen, inode, path);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("set_cifs_acl rc: %d", rc));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(pnntsd);
|
||||||
|
kfree(pntsd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rc);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||||
|
@@ -237,6 +237,9 @@
|
|||||||
| DELETE | READ_CONTROL | WRITE_DAC \
|
| DELETE | READ_CONTROL | WRITE_DAC \
|
||||||
| WRITE_OWNER | SYNCHRONIZE)
|
| WRITE_OWNER | SYNCHRONIZE)
|
||||||
|
|
||||||
|
#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
|
||||||
|
| READ_CONTROL | SYNCHRONIZE)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalid readdir handle
|
* Invalid readdir handle
|
||||||
|
@@ -97,7 +97,7 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
|
|||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
struct super_block *sb, int xid);
|
struct super_block *sb, int xid);
|
||||||
extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
|
extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
|
||||||
extern int mode_to_acl(struct inode *inode, const char *path);
|
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
|
||||||
|
|
||||||
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
||||||
const char *);
|
const char *);
|
||||||
@@ -342,6 +342,8 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
|||||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||||
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
||||||
|
extern int CIFSSMBSetCIFSACL(const int, struct cifsTconInfo *, __u16,
|
||||||
|
struct cifs_ntsd *, __u32);
|
||||||
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *searchName,
|
const unsigned char *searchName,
|
||||||
char *acl_inf, const int buflen, const int acl_type,
|
char *acl_inf, const int buflen, const int acl_type,
|
||||||
|
@@ -3156,6 +3156,71 @@ qsec_out:
|
|||||||
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||||
|
struct cifs_ntsd *pntsd, __u32 acllen)
|
||||||
|
{
|
||||||
|
__u16 byte_count, param_count, data_count, param_offset, data_offset;
|
||||||
|
int rc = 0;
|
||||||
|
int bytes_returned = 0;
|
||||||
|
SET_SEC_DESC_REQ *pSMB = NULL;
|
||||||
|
NTRANSACT_RSP *pSMBr = NULL;
|
||||||
|
|
||||||
|
setCifsAclRetry:
|
||||||
|
rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
|
||||||
|
(void **) &pSMBr);
|
||||||
|
if (rc)
|
||||||
|
return (rc);
|
||||||
|
|
||||||
|
pSMB->MaxSetupCount = 0;
|
||||||
|
pSMB->Reserved = 0;
|
||||||
|
|
||||||
|
param_count = 8;
|
||||||
|
param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
|
||||||
|
data_count = acllen;
|
||||||
|
data_offset = param_offset + param_count;
|
||||||
|
byte_count = 3 /* pad */ + param_count;
|
||||||
|
|
||||||
|
pSMB->DataCount = cpu_to_le32(data_count);
|
||||||
|
pSMB->TotalDataCount = pSMB->DataCount;
|
||||||
|
pSMB->MaxParameterCount = cpu_to_le32(4);
|
||||||
|
pSMB->MaxDataCount = cpu_to_le32(16384);
|
||||||
|
pSMB->ParameterCount = cpu_to_le32(param_count);
|
||||||
|
pSMB->ParameterOffset = cpu_to_le32(param_offset);
|
||||||
|
pSMB->TotalParameterCount = pSMB->ParameterCount;
|
||||||
|
pSMB->DataOffset = cpu_to_le32(data_offset);
|
||||||
|
pSMB->SetupCount = 0;
|
||||||
|
pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
|
||||||
|
pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
|
||||||
|
|
||||||
|
pSMB->Fid = fid; /* file handle always le */
|
||||||
|
pSMB->Reserved2 = 0;
|
||||||
|
pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
|
||||||
|
|
||||||
|
if (pntsd && acllen) {
|
||||||
|
memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
|
||||||
|
(char *) pntsd,
|
||||||
|
acllen);
|
||||||
|
pSMB->hdr.smb_buf_length += (byte_count + data_count);
|
||||||
|
|
||||||
|
} else
|
||||||
|
pSMB->hdr.smb_buf_length += byte_count;
|
||||||
|
|
||||||
|
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||||
|
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||||
|
|
||||||
|
cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
|
||||||
|
if (rc)
|
||||||
|
cFYI(1, ("Set CIFS ACL returned %d", rc));
|
||||||
|
cifs_buf_release(pSMB);
|
||||||
|
|
||||||
|
if (rc == -EAGAIN)
|
||||||
|
goto setCifsAclRetry;
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||||
|
|
||||||
/* Legacy Query Path Information call for lookup to old servers such
|
/* Legacy Query Path Information call for lookup to old servers such
|
||||||
|
@@ -1607,7 +1607,13 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
else if (attrs->ia_valid & ATTR_MODE) {
|
else if (attrs->ia_valid & ATTR_MODE) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
|
||||||
|
rc = mode_to_acl(direntry->d_inode, full_path, mode);
|
||||||
|
else if ((mode & S_IWUGO) == 0) /* not writeable */ {
|
||||||
|
#else
|
||||||
if ((mode & S_IWUGO) == 0) /* not writeable */ {
|
if ((mode & S_IWUGO) == 0) /* not writeable */ {
|
||||||
|
#endif
|
||||||
if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
|
if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
|
||||||
set_dosattr = TRUE;
|
set_dosattr = TRUE;
|
||||||
time_buf.Attributes =
|
time_buf.Attributes =
|
||||||
@@ -1626,10 +1632,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||||||
if (time_buf.Attributes == 0)
|
if (time_buf.Attributes == 0)
|
||||||
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
||||||
}
|
}
|
||||||
/* BB to be implemented -
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
via Windows security descriptors or streams */
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
|
||||||
/* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
mode_to_acl(direntry->d_inode, full_path, mode);
|
||||||
cifs_sb->local_nls); */
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs->ia_valid & ATTR_ATIME) {
|
if (attrs->ia_valid & ATTR_ATIME) {
|
||||||
|
Reference in New Issue
Block a user