Commit 3921b8ae authored by Steve French's avatar Steve French

[CIFS] POSIX ACL support part 1

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent d14353f9
...@@ -90,5 +90,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -90,5 +90,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.24" #define CIFS_VERSION "1.25"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -1076,6 +1076,7 @@ struct smb_t2_rsp { ...@@ -1076,6 +1076,7 @@ struct smb_t2_rsp {
#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B #define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
#define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_BASIC 0x200
#define SMB_QUERY_FILE_UNIX_LINK 0x201 #define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_QUERY_POSIX_ACL 0x204
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
...@@ -1090,6 +1091,7 @@ struct smb_t2_rsp { ...@@ -1090,6 +1091,7 @@ struct smb_t2_rsp {
#define SMB_SET_FILE_END_OF_FILE_INFO 0x104 #define SMB_SET_FILE_END_OF_FILE_INFO 0x104
#define SMB_SET_FILE_UNIX_BASIC 0x200 #define SMB_SET_FILE_UNIX_BASIC 0x200
#define SMB_SET_FILE_UNIX_LINK 0x201 #define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_POSIX_ACL 0x204
#define SMB_SET_FILE_UNIX_HLINK 0x203 #define SMB_SET_FILE_UNIX_HLINK 0x203
#define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
...@@ -1638,6 +1640,27 @@ struct file_compression_info { ...@@ -1638,6 +1640,27 @@ struct file_compression_info {
__u8 pad[3]; __u8 pad[3];
}; /* level 0x10b */ }; /* level 0x10b */
/* POSIX ACL set/query path info structures */
#define CIFS_ACL_VERSION 1
struct cifs_posix_acl {
/* BB fixme add here */
}; /* level 0x204 */
/* types of access control entries */
#define CIFS_POSIX_ACL_USER_OBJ 0x01
#define CIFS_POSIX_ACL_USER 0x02
#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
#define CIFS_POSIX_ACL_GROUP 0x08
#define CIFS_POSIX_ACL_MASK 0x10
#define CIFS_POSIX_ACL_OTHER 0x20
/* types of perms */
#define CIFS_POSIX_ACL_EXECUTE 0x01
#define CIFS_POSIX_ACL_WRITE 0x02
#define CIFS_POSIX_ACL_READ 0x04
/* end of POSIX ACL definitions */
struct file_internal_info { struct file_internal_info {
__u64 UniqueId; /* inode number */ __u64 UniqueId; /* inode number */
}; /* level 0x3ee */ }; /* level 0x3ee */
......
...@@ -1585,6 +1585,96 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1585,6 +1585,96 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
return rc; return rc;
} }
#ifdef CONFIG_CIFS_POSIX
int
CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_POSIX_ACL */
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned;
int name_len;
__u16 params, byte_count;
cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
queryAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
/* BB fixme find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
pSMB->FileName[name_len] = 0;
pSMB->FileName[name_len+1] = 0;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530 /* BB fixme */);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max data count below from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
} else {
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < 2))
/* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
memcpy(acl_inf,(char *)&pSMBr->hdr.Protocol+data_offset,
min_t(const int, buflen, count));
}
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto queryAclRetry;
return rc;
}
#endif
int int
CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, const unsigned char *searchName,
...@@ -1880,8 +1970,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -1880,8 +1970,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
byte_count = params + 1 /* pad */ ; byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct pSMB->ParameterOffset = cpu_to_le16(
smb_com_transaction2_ffirst_req, SearchAttributes) - 4); offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->DataCount = 0; pSMB->DataCount = 0;
pSMB->DataOffset = 0; pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
...@@ -1997,8 +2087,8 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, ...@@ -1997,8 +2087,8 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
byte_count = params + 1 /* pad */ ; byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct pSMB->ParameterOffset = cpu_to_le16(
smb_com_transaction2_ffirst_req, SearchAttributes) - 4); offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->DataCount = 0; pSMB->DataCount = 0;
pSMB->DataOffset = 0; pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
......
...@@ -75,7 +75,7 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p ...@@ -75,7 +75,7 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p
} }
/* find the corresponding entry in the search */ /* find the corresponding entry in the search */
static int find_cifs_entry(const int xid, const struct cifsTconInfo * pTcon, static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
const loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */) const loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */)
{ {
int rc = 0; int rc = 0;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/posix_acl_xattr.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -27,10 +28,10 @@ ...@@ -27,10 +28,10 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#define MAX_EA_VALUE_SIZE 65535 #define MAX_EA_VALUE_SIZE 65535
#define CIFS_XATTR_DOS_ATTRIB "user.DOSATTRIB" #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
#define CIFS_XATTR_USER_PREFIX "user." #define CIFS_XATTR_USER_PREFIX "user."
#define CIFS_XATTR_SYSTEM_PREFIX "system." #define CIFS_XATTR_SYSTEM_PREFIX "system."
#define CIFS_XATTR_OS2_PREFIX "OS2." /* BB should check for this someday */ #define CIFS_XATTR_OS2_PREFIX "os2." /* BB should check for this someday */
/* also note could add check for security prefix XATTR_SECURITY_PREFIX */ /* also note could add check for security prefix XATTR_SECURITY_PREFIX */
...@@ -128,16 +129,30 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, ...@@ -128,16 +129,30 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
if(ea_name == NULL) { if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported")); cFYI(1,("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) { } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to set cifs inode metadata"));
}
ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} else {
if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS) == 0)) {
cFYI(1,("set POSIX ACL not supported yet"));
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
cFYI(1,("set default POSIX ACL not supported yet"));
} else {
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
/* BB what if no namespace prefix? */ /* BB what if no namespace prefix? */
/* Should we just pass them to server, except for /* Should we just pass them to server, except for
system and perhaps security prefixes? */ system and perhaps security prefixes? */
} else {
ea_name+=5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} }
}
if (full_path) if (full_path)
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
...@@ -177,19 +192,43 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ...@@ -177,19 +192,43 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) { if(ea_name == NULL) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); cFYI(1,("Null xattr names not supported"));
/* BB what if no namespace prefix? */ } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
/* Should we just pass them to server, except for system? */ if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to query cifs inode metadata"));
/* revalidate/getattr then populate from inode */
} /* BB add else when above is implemented */
ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
} else {
if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
cFYI(1,("query POSIX ACL not supported yet"));
/* rc = CIFSSMBGetPosixACL(xid, pTcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
cifs_sb->local_nls); */
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
cFYI(1,("query default POSIX ACL not supported yet"));
/* rc = CIFSSMBGetPosixACL(xid, pTcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
cifs_sb->local_nls); */
} else { } else {
/* We could add a check here cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
}
}
/* We could add an additional check for streams ie
if proc/fs/cifs/streamstoxattr is set then if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to search server for EAs or streams to
returns as xattrs */ returns as xattrs */
ea_name+=5; /* skip past user. */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
}
if (full_path) if (full_path)
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment