diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/CHANGES | 4 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 89 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 179 | ||||
-rw-r--r-- | fs/cifs/connect.c | 7 | ||||
-rw-r--r-- | fs/cifs/transport.c | 1 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 22 |
9 files changed, 292 insertions, 20 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 1d2137561c55..c7995c96f069 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,7 +1,9 @@ | |||
1 | Version 1.40 | 1 | Version 1.40 |
2 | ------------ | 2 | ------------ |
3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance | 3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance |
4 | of readpages by eliminating one extra memcpy. | 4 | of readpages by eliminating one extra memcpy. Allow update of file size |
5 | from remote server even if file is open for write as long as mount is | ||
6 | directio. | ||
5 | 7 | ||
6 | Version 1.39 | 8 | Version 1.39 |
7 | ------------ | 9 | ------------ |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index f799f6f0e729..ad58eb0c4d6d 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -24,9 +24,10 @@ | |||
24 | #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ | 24 | #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ |
25 | #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ | 25 | #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ |
26 | #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ | 26 | #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ |
27 | #define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ | 27 | #define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ |
28 | #define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ | 28 | #define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ |
29 | #define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ | 29 | #define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ |
30 | #define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ | ||
30 | 31 | ||
31 | struct cifs_sb_info { | 32 | struct cifs_sb_info { |
32 | struct cifsTconInfo *tcon; /* primary mount */ | 33 | struct cifsTconInfo *tcon; /* primary mount */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 862e403ff211..7bed27601ce5 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -233,6 +233,8 @@ struct cifsTconInfo { | |||
233 | atomic_t num_hardlinks; | 233 | atomic_t num_hardlinks; |
234 | atomic_t num_symlinks; | 234 | atomic_t num_symlinks; |
235 | atomic_t num_locks; | 235 | atomic_t num_locks; |
236 | atomic_t num_acl_get; | ||
237 | atomic_t num_acl_set; | ||
236 | #ifdef CONFIG_CIFS_STATS2 | 238 | #ifdef CONFIG_CIFS_STATS2 |
237 | unsigned long long time_writes; | 239 | unsigned long long time_writes; |
238 | unsigned long long time_reads; | 240 | unsigned long long time_reads; |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 3c09fb9cc569..cc2471094ca5 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -528,7 +528,7 @@ typedef union smb_com_session_setup_andx { | |||
528 | /* STRING PrimaryDomain */ | 528 | /* STRING PrimaryDomain */ |
529 | /* STRING NativeOS */ | 529 | /* STRING NativeOS */ |
530 | /* STRING NativeLanMan */ | 530 | /* STRING NativeLanMan */ |
531 | } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */ | 531 | } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */ |
532 | 532 | ||
533 | struct { /* default (NTLM) response format */ | 533 | struct { /* default (NTLM) response format */ |
534 | struct smb_hdr hdr; /* wct = 3 */ | 534 | struct smb_hdr hdr; /* wct = 3 */ |
@@ -540,7 +540,7 @@ typedef union smb_com_session_setup_andx { | |||
540 | unsigned char NativeOS[1]; /* followed by */ | 540 | unsigned char NativeOS[1]; /* followed by */ |
541 | /* unsigned char * NativeLanMan; */ | 541 | /* unsigned char * NativeLanMan; */ |
542 | /* unsigned char * PrimaryDomain; */ | 542 | /* unsigned char * PrimaryDomain; */ |
543 | } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */ | 543 | } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */ |
544 | } __attribute__((packed)) SESSION_SETUP_ANDX; | 544 | } __attribute__((packed)) SESSION_SETUP_ANDX; |
545 | 545 | ||
546 | #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" | 546 | #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" |
@@ -1007,10 +1007,49 @@ typedef struct smb_com_setattr_rsp { | |||
1007 | 1007 | ||
1008 | /* empty wct response to setattr */ | 1008 | /* empty wct response to setattr */ |
1009 | 1009 | ||
1010 | /***************************************************/ | 1010 | /*******************************************************/ |
1011 | /* NT Transact structure defintions follow */ | 1011 | /* NT Transact structure defintions follow */ |
1012 | /* Currently only ioctl and notify are implemented */ | 1012 | /* Currently only ioctl, acl (get security descriptor) */ |
1013 | /***************************************************/ | 1013 | /* and notify are implemented */ |
1014 | /*******************************************************/ | ||
1015 | typedef struct smb_com_ntransact_req { | ||
1016 | struct smb_hdr hdr; /* wct >= 19 */ | ||
1017 | __u8 MaxSetupCount; | ||
1018 | __u16 Reserved; | ||
1019 | __le32 TotalParameterCount; | ||
1020 | __le32 TotalDataCount; | ||
1021 | __le32 MaxParameterCount; | ||
1022 | __le32 MaxDataCount; | ||
1023 | __le32 ParameterCount; | ||
1024 | __le32 ParameterOffset; | ||
1025 | __le32 DataCount; | ||
1026 | __le32 DataOffset; | ||
1027 | __u8 SetupCount; /* four setup words follow subcommand */ | ||
1028 | /* SNIA spec incorrectly included spurious pad here */ | ||
1029 | __le16 SubCommand; /* 2 = IOCTL/FSCTL */ | ||
1030 | /* SetupCount words follow then */ | ||
1031 | __le16 ByteCount; | ||
1032 | __u8 Pad[3]; | ||
1033 | __u8 Parms[0]; | ||
1034 | } __attribute__((packed)) NTRANSACT_REQ; | ||
1035 | |||
1036 | typedef struct smb_com_ntransact_rsp { | ||
1037 | struct smb_hdr hdr; /* wct = 18 */ | ||
1038 | __u8 Reserved[3]; | ||
1039 | __le32 TotalParameterCount; | ||
1040 | __le32 TotalDataCount; | ||
1041 | __le32 ParameterCount; | ||
1042 | __le32 ParameterOffset; | ||
1043 | __le32 ParameterDisplacement; | ||
1044 | __le32 DataCount; | ||
1045 | __le32 DataOffset; | ||
1046 | __le32 DataDisplacement; | ||
1047 | __u8 SetupCount; /* 0 */ | ||
1048 | __u16 ByteCount; | ||
1049 | /* __u8 Pad[3]; */ | ||
1050 | /* parms and data follow */ | ||
1051 | } __attribute__((packed)) NTRANSACT_RSP; | ||
1052 | |||
1014 | typedef struct smb_com_transaction_ioctl_req { | 1053 | typedef struct smb_com_transaction_ioctl_req { |
1015 | struct smb_hdr hdr; /* wct = 23 */ | 1054 | struct smb_hdr hdr; /* wct = 23 */ |
1016 | __u8 MaxSetupCount; | 1055 | __u8 MaxSetupCount; |
@@ -1025,11 +1064,11 @@ typedef struct smb_com_transaction_ioctl_req { | |||
1025 | __le32 DataOffset; | 1064 | __le32 DataOffset; |
1026 | __u8 SetupCount; /* four setup words follow subcommand */ | 1065 | __u8 SetupCount; /* four setup words follow subcommand */ |
1027 | /* SNIA spec incorrectly included spurious pad here */ | 1066 | /* SNIA spec incorrectly included spurious pad here */ |
1028 | __le16 SubCommand;/* 2 = IOCTL/FSCTL */ | 1067 | __le16 SubCommand; /* 2 = IOCTL/FSCTL */ |
1029 | __le32 FunctionCode; | 1068 | __le32 FunctionCode; |
1030 | __u16 Fid; | 1069 | __u16 Fid; |
1031 | __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/ | 1070 | __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */ |
1032 | __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/ | 1071 | __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */ |
1033 | __le16 ByteCount; | 1072 | __le16 ByteCount; |
1034 | __u8 Pad[3]; | 1073 | __u8 Pad[3]; |
1035 | __u8 Data[1]; | 1074 | __u8 Data[1]; |
@@ -1049,9 +1088,35 @@ typedef struct smb_com_transaction_ioctl_rsp { | |||
1049 | __u8 SetupCount; /* 1 */ | 1088 | __u8 SetupCount; /* 1 */ |
1050 | __le16 ReturnedDataLen; | 1089 | __le16 ReturnedDataLen; |
1051 | __u16 ByteCount; | 1090 | __u16 ByteCount; |
1052 | __u8 Pad[3]; | ||
1053 | } __attribute__((packed)) TRANSACT_IOCTL_RSP; | 1091 | } __attribute__((packed)) TRANSACT_IOCTL_RSP; |
1054 | 1092 | ||
1093 | #define CIFS_ACL_OWNER 1 | ||
1094 | #define CIFS_ACL_GROUP 2 | ||
1095 | #define CIFS_ACL_DACL 4 | ||
1096 | #define CIFS_ACL_SACL 8 | ||
1097 | |||
1098 | typedef struct smb_com_transaction_qsec_req { | ||
1099 | struct smb_hdr hdr; /* wct = 19 */ | ||
1100 | __u8 MaxSetupCount; | ||
1101 | __u16 Reserved; | ||
1102 | __le32 TotalParameterCount; | ||
1103 | __le32 TotalDataCount; | ||
1104 | __le32 MaxParameterCount; | ||
1105 | __le32 MaxDataCount; | ||
1106 | __le32 ParameterCount; | ||
1107 | __le32 ParameterOffset; | ||
1108 | __le32 DataCount; | ||
1109 | __le32 DataOffset; | ||
1110 | __u8 SetupCount; /* no setup words follow subcommand */ | ||
1111 | /* SNIA spec incorrectly included spurious pad here */ | ||
1112 | __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */ | ||
1113 | __le16 ByteCount; /* bcc = 3 + 8 */ | ||
1114 | __u8 Pad[3]; | ||
1115 | __u16 Fid; | ||
1116 | __u16 Reserved2; | ||
1117 | __le32 AclFlags; | ||
1118 | } __attribute__((packed)) QUERY_SEC_DESC_REQ; | ||
1119 | |||
1055 | typedef struct smb_com_transaction_change_notify_req { | 1120 | typedef struct smb_com_transaction_change_notify_req { |
1056 | struct smb_hdr hdr; /* wct = 23 */ | 1121 | struct smb_hdr hdr; /* wct = 23 */ |
1057 | __u8 MaxSetupCount; | 1122 | __u8 MaxSetupCount; |
@@ -1072,10 +1137,12 @@ typedef struct smb_com_transaction_change_notify_req { | |||
1072 | __u8 WatchTree; /* 1 = Monitor subdirectories */ | 1137 | __u8 WatchTree; /* 1 = Monitor subdirectories */ |
1073 | __u8 Reserved2; | 1138 | __u8 Reserved2; |
1074 | __le16 ByteCount; | 1139 | __le16 ByteCount; |
1075 | /* __u8 Pad[3];*/ | 1140 | /* __u8 Pad[3];*/ |
1076 | /* __u8 Data[1];*/ | 1141 | /* __u8 Data[1];*/ |
1077 | } __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; | 1142 | } __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; |
1078 | 1143 | ||
1144 | /* BB eventually change to use generic ntransact rsp struct | ||
1145 | and validation routine */ | ||
1079 | typedef struct smb_com_transaction_change_notify_rsp { | 1146 | typedef struct smb_com_transaction_change_notify_rsp { |
1080 | struct smb_hdr hdr; /* wct = 18 */ | 1147 | struct smb_hdr hdr; /* wct = 18 */ |
1081 | __u8 Reserved[3]; | 1148 | __u8 Reserved[3]; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8ef0ce47f5b6..3c03aadaff0c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -299,6 +299,9 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | |||
299 | const char *fileName, const char * ea_name, | 299 | const char *fileName, const char * ea_name, |
300 | const void * ea_value, const __u16 ea_value_len, | 300 | const void * ea_value, const __u16 ea_value_len, |
301 | const struct nls_table *nls_codepage, int remap_special_chars); | 301 | const struct nls_table *nls_codepage, int remap_special_chars); |
302 | extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, | ||
303 | __u16 fid, char *acl_inf, const int buflen, | ||
304 | const int acl_type /* ACCESS vs. DEFAULT */); | ||
302 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 305 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, |
303 | const unsigned char *searchName, | 306 | const unsigned char *searchName, |
304 | char *acl_inf, const int buflen,const int acl_type, | 307 | char *acl_inf, const int buflen,const int acl_type, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1620991cd4d2..20300bc9ae77 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1926,6 +1926,90 @@ querySymLinkRetry: | |||
1926 | return rc; | 1926 | return rc; |
1927 | } | 1927 | } |
1928 | 1928 | ||
1929 | /* Initialize NT TRANSACT SMB into small smb request buffer. | ||
1930 | This assumes that all NT TRANSACTS that we init here have | ||
1931 | total parm and data under about 400 bytes (to fit in small cifs | ||
1932 | buffer size), which is the case so far, it easily fits. NB: | ||
1933 | Setup words themselves and ByteCount | ||
1934 | MaxSetupCount (size of returned setup area) and | ||
1935 | MaxParameterCount (returned parms size) must be set by caller */ | ||
1936 | static int | ||
1937 | smb_init_ntransact(const __u16 sub_command, const int setup_count, | ||
1938 | const int parm_len, struct cifsTconInfo *tcon, | ||
1939 | void ** ret_buf) | ||
1940 | { | ||
1941 | int rc; | ||
1942 | __u32 temp_offset; | ||
1943 | struct smb_com_ntransact_req * pSMB; | ||
1944 | |||
1945 | rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, | ||
1946 | (void **)&pSMB); | ||
1947 | if (rc) | ||
1948 | return rc; | ||
1949 | *ret_buf = (void *)pSMB; | ||
1950 | pSMB->Reserved = 0; | ||
1951 | pSMB->TotalParameterCount = cpu_to_le32(parm_len); | ||
1952 | pSMB->TotalDataCount = 0; | ||
1953 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
1954 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
1955 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
1956 | pSMB->DataCount = pSMB->TotalDataCount; | ||
1957 | temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + | ||
1958 | (setup_count * 2) - 4 /* for rfc1001 length itself */; | ||
1959 | pSMB->ParameterOffset = cpu_to_le32(temp_offset); | ||
1960 | pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); | ||
1961 | pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ | ||
1962 | pSMB->SubCommand = cpu_to_le16(sub_command); | ||
1963 | return 0; | ||
1964 | } | ||
1965 | |||
1966 | static int | ||
1967 | validate_ntransact(char * buf, char ** ppparm, char ** ppdata, | ||
1968 | int * pdatalen, int * pparmlen) | ||
1969 | { | ||
1970 | char * end_of_smb; | ||
1971 | __u32 data_count, data_offset, parm_count, parm_offset; | ||
1972 | struct smb_com_ntransact_rsp * pSMBr; | ||
1973 | |||
1974 | if(buf == NULL) | ||
1975 | return -EINVAL; | ||
1976 | |||
1977 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | ||
1978 | |||
1979 | /* ByteCount was converted from little endian in SendReceive */ | ||
1980 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | ||
1981 | (char *)&pSMBr->ByteCount; | ||
1982 | |||
1983 | |||
1984 | data_offset = le32_to_cpu(pSMBr->DataOffset); | ||
1985 | data_count = le32_to_cpu(pSMBr->DataCount); | ||
1986 | parm_offset = le32_to_cpu(pSMBr->ParameterOffset); | ||
1987 | parm_count = le32_to_cpu(pSMBr->ParameterCount); | ||
1988 | |||
1989 | *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; | ||
1990 | *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; | ||
1991 | |||
1992 | /* should we also check that parm and data areas do not overlap? */ | ||
1993 | if(*ppparm > end_of_smb) { | ||
1994 | cFYI(1,("parms start after end of smb")); | ||
1995 | return -EINVAL; | ||
1996 | } else if(parm_count + *ppparm > end_of_smb) { | ||
1997 | cFYI(1,("parm end after end of smb")); | ||
1998 | return -EINVAL; | ||
1999 | } else if(*ppdata > end_of_smb) { | ||
2000 | cFYI(1,("data starts after end of smb")); | ||
2001 | return -EINVAL; | ||
2002 | } else if(data_count + *ppdata > end_of_smb) { | ||
2003 | cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", | ||
2004 | *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */ | ||
2005 | return -EINVAL; | ||
2006 | } else if(parm_count + data_count > pSMBr->ByteCount) { | ||
2007 | cFYI(1,("parm count and data count larger than SMB")); | ||
2008 | return -EINVAL; | ||
2009 | } | ||
2010 | return 0; | ||
2011 | } | ||
2012 | |||
1929 | int | 2013 | int |
1930 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2014 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
1931 | const unsigned char *searchName, | 2015 | const unsigned char *searchName, |
@@ -1948,7 +2032,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1948 | pSMB->TotalDataCount = 0; | 2032 | pSMB->TotalDataCount = 0; |
1949 | pSMB->MaxParameterCount = cpu_to_le32(2); | 2033 | pSMB->MaxParameterCount = cpu_to_le32(2); |
1950 | /* BB find exact data count max from sess structure BB */ | 2034 | /* BB find exact data count max from sess structure BB */ |
1951 | pSMB->MaxDataCount = cpu_to_le32(4000); | 2035 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - |
2036 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
1952 | pSMB->MaxSetupCount = 4; | 2037 | pSMB->MaxSetupCount = 4; |
1953 | pSMB->Reserved = 0; | 2038 | pSMB->Reserved = 0; |
1954 | pSMB->ParameterOffset = 0; | 2039 | pSMB->ParameterOffset = 0; |
@@ -1975,7 +2060,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1975 | rc = -EIO; /* bad smb */ | 2060 | rc = -EIO; /* bad smb */ |
1976 | else { | 2061 | else { |
1977 | if(data_count && (data_count < 2048)) { | 2062 | if(data_count && (data_count < 2048)) { |
1978 | char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount; | 2063 | char * end_of_smb = 2 /* sizeof byte count */ + |
2064 | pSMBr->ByteCount + | ||
2065 | (char *)&pSMBr->ByteCount; | ||
1979 | 2066 | ||
1980 | struct reparse_data * reparse_buf = (struct reparse_data *) | 2067 | struct reparse_data * reparse_buf = (struct reparse_data *) |
1981 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 2068 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
@@ -2219,6 +2306,7 @@ queryAclRetry: | |||
2219 | 2306 | ||
2220 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2307 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2221 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2308 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
2309 | cifs_stats_inc(&tcon->num_acl_get); | ||
2222 | if (rc) { | 2310 | if (rc) { |
2223 | cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); | 2311 | cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); |
2224 | } else { | 2312 | } else { |
@@ -2406,6 +2494,87 @@ GetExtAttrOut: | |||
2406 | 2494 | ||
2407 | #endif /* CONFIG_POSIX */ | 2495 | #endif /* CONFIG_POSIX */ |
2408 | 2496 | ||
2497 | /* Convert CIFS ACL to POSIX form */ | ||
2498 | static int parse_sec_desc(struct sec_desc * psec_desc, int acl_len) | ||
2499 | { | ||
2500 | CHECK ON OTHER COMPUTER TO SEE IF FORMAT ENCODED IN CIFSPDU.H ALREADY | ||
2501 | return 0; | ||
2502 | } | ||
2503 | |||
2504 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | ||
2505 | int | ||
2506 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | ||
2507 | /* BB fix up return info */ char *acl_inf, const int buflen, | ||
2508 | const int acl_type /* ACCESS/DEFAULT not sure implication */) | ||
2509 | { | ||
2510 | int rc = 0; | ||
2511 | int buf_type = 0; | ||
2512 | QUERY_SEC_DESC_REQ * pSMB; | ||
2513 | struct kvec iov[1]; | ||
2514 | |||
2515 | cFYI(1, ("GetCifsACL")); | ||
2516 | |||
2517 | rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, | ||
2518 | 8 /* parm len */, tcon, (void **) &pSMB); | ||
2519 | if (rc) | ||
2520 | return rc; | ||
2521 | |||
2522 | pSMB->MaxParameterCount = cpu_to_le32(4); | ||
2523 | /* BB TEST with big acls that might need to be e.g. larger than 16K */ | ||
2524 | pSMB->MaxSetupCount = 0; | ||
2525 | pSMB->Fid = fid; /* file handle always le */ | ||
2526 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | | ||
2527 | CIFS_ACL_DACL); | ||
2528 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ | ||
2529 | pSMB->hdr.smb_buf_length += 11; | ||
2530 | iov[0].iov_base = (char *)pSMB; | ||
2531 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | ||
2532 | |||
2533 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0); | ||
2534 | cifs_stats_inc(&tcon->num_acl_get); | ||
2535 | if (rc) { | ||
2536 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); | ||
2537 | } else { /* decode response */ | ||
2538 | struct sec_desc * psec_desc; | ||
2539 | __le32 * parm; | ||
2540 | int parm_len; | ||
2541 | int data_len; | ||
2542 | int acl_len; | ||
2543 | struct smb_com_ntransact_rsp * pSMBr; | ||
2544 | |||
2545 | /* validate_nttransact */ | ||
2546 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, | ||
2547 | (char **)&psec_desc, | ||
2548 | &parm_len, &data_len); | ||
2549 | |||
2550 | if(rc) | ||
2551 | goto qsec_out; | ||
2552 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; | ||
2553 | |||
2554 | cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */ | ||
2555 | |||
2556 | if (le32_to_cpu(pSMBr->ParameterCount) != 4) { | ||
2557 | rc = -EIO; /* bad smb */ | ||
2558 | goto qsec_out; | ||
2559 | } | ||
2560 | |||
2561 | /* BB check that data area is minimum length and as big as acl_len */ | ||
2562 | |||
2563 | acl_len = le32_to_cpu(*(__le32 *)parm); | ||
2564 | /* BB check if(acl_len > bufsize) */ | ||
2565 | |||
2566 | parse_sec_desc(psec_desc, acl_len); | ||
2567 | } | ||
2568 | qsec_out: | ||
2569 | if(buf_type == CIFS_SMALL_BUFFER) | ||
2570 | cifs_small_buf_release(iov[0].iov_base); | ||
2571 | else if(buf_type == CIFS_LARGE_BUFFER) | ||
2572 | cifs_buf_release(iov[0].iov_base); | ||
2573 | cifs_small_buf_release(pSMB); | ||
2574 | return rc; | ||
2575 | } | ||
2576 | |||
2577 | |||
2409 | /* Legacy Query Path Information call for lookup to old servers such | 2578 | /* Legacy Query Path Information call for lookup to old servers such |
2410 | as Win9x/WinME */ | 2579 | as Win9x/WinME */ |
2411 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 2580 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, |
@@ -4304,7 +4473,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
4304 | { | 4473 | { |
4305 | int rc = 0; | 4474 | int rc = 0; |
4306 | struct smb_com_transaction_change_notify_req * pSMB = NULL; | 4475 | struct smb_com_transaction_change_notify_req * pSMB = NULL; |
4307 | struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; | 4476 | struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL; |
4308 | struct dir_notify_req *dnotify_req; | 4477 | struct dir_notify_req *dnotify_req; |
4309 | int bytes_returned; | 4478 | int bytes_returned; |
4310 | 4479 | ||
@@ -4319,6 +4488,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
4319 | pSMB->MaxParameterCount = cpu_to_le32(2); | 4488 | pSMB->MaxParameterCount = cpu_to_le32(2); |
4320 | /* BB find exact data count max from sess structure BB */ | 4489 | /* BB find exact data count max from sess structure BB */ |
4321 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | 4490 | pSMB->MaxDataCount = 0; /* same in little endian or be */ |
4491 | /* BB VERIFY verify which is correct for above BB */ | ||
4492 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
4493 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
4494 | |||
4322 | pSMB->MaxSetupCount = 4; | 4495 | pSMB->MaxSetupCount = 4; |
4323 | pSMB->Reserved = 0; | 4496 | pSMB->Reserved = 0; |
4324 | pSMB->ParameterOffset = 0; | 4497 | pSMB->ParameterOffset = 0; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 45c9d726c002..1817d5313a8a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -76,6 +76,7 @@ struct smb_vol { | |||
76 | unsigned setuids:1; | 76 | unsigned setuids:1; |
77 | unsigned noperm:1; | 77 | unsigned noperm:1; |
78 | unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ | 78 | unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ |
79 | unsigned cifs_acl:1; | ||
79 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 80 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
80 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 81 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
81 | unsigned direct_io:1; | 82 | unsigned direct_io:1; |
@@ -1159,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1159 | vol->server_ino = 1; | 1160 | vol->server_ino = 1; |
1160 | } else if (strnicmp(data, "noserverino",9) == 0) { | 1161 | } else if (strnicmp(data, "noserverino",9) == 0) { |
1161 | vol->server_ino = 0; | 1162 | vol->server_ino = 0; |
1163 | } else if (strnicmp(data, "cifsacl",7) == 0) { | ||
1164 | vol->cifs_acl = 1; | ||
1165 | } else if (strnicmp(data, "nocifsacl", 9) == 0) { | ||
1166 | vol->cifs_acl = 0; | ||
1162 | } else if (strnicmp(data, "acl",3) == 0) { | 1167 | } else if (strnicmp(data, "acl",3) == 0) { |
1163 | vol->no_psx_acl = 0; | 1168 | vol->no_psx_acl = 0; |
1164 | } else if (strnicmp(data, "noacl",5) == 0) { | 1169 | } else if (strnicmp(data, "noacl",5) == 0) { |
@@ -1806,6 +1811,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1806 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | 1811 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; |
1807 | if(volume_info.nobrl) | 1812 | if(volume_info.nobrl) |
1808 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | 1813 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; |
1814 | if(volume_info.cifs_acl) | ||
1815 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; | ||
1809 | 1816 | ||
1810 | if(volume_info.direct_io) { | 1817 | if(volume_info.direct_io) { |
1811 | cFYI(1,("mounting share using direct i/o")); | 1818 | cFYI(1,("mounting share using direct i/o")); |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index c96a148c39b2..7b98792150ea 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -489,7 +489,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
489 | receive_len, xid)); | 489 | receive_len, xid)); |
490 | rc = -EIO; | 490 | rc = -EIO; |
491 | } else { /* rcvd frame is ok */ | 491 | } else { /* rcvd frame is ok */ |
492 | |||
493 | if (midQ->resp_buf && | 492 | if (midQ->resp_buf && |
494 | (midQ->midState == MID_RESPONSE_RECEIVED)) { | 493 | (midQ->midState == MID_RESPONSE_RECEIVED)) { |
495 | 494 | ||
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index f375f87c7dbd..777e3363c2a4 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -254,7 +254,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, | |||
254 | rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, | 254 | rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, |
255 | buf_size, cifs_sb->local_nls, | 255 | buf_size, cifs_sb->local_nls, |
256 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 256 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
257 | } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | 257 | } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, |
258 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | ||
258 | #ifdef CONFIG_CIFS_POSIX | 259 | #ifdef CONFIG_CIFS_POSIX |
259 | if(sb->s_flags & MS_POSIXACL) | 260 | if(sb->s_flags & MS_POSIXACL) |
260 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 261 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |
@@ -262,10 +263,27 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, | |||
262 | cifs_sb->local_nls, | 263 | cifs_sb->local_nls, |
263 | cifs_sb->mnt_cifs_flags & | 264 | cifs_sb->mnt_cifs_flags & |
264 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 265 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
266 | /* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
267 | __u16 fid; | ||
268 | int oplock = FALSE; | ||
269 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
270 | FILE_OPEN, GENERIC_READ, 0, &fid, | ||
271 | &oplock, NULL, cifs_sb->local_nls, | ||
272 | cifs_sb->mnt_cifs_flags & | ||
273 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
274 | if(rc == 0) { | ||
275 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, | ||
276 | ea_value, buf_size, | ||
277 | ACL_TYPE_ACCESS); | ||
278 | CIFSSMBClose(xid, pTcon, fid) | ||
279 | } | ||
280 | } */ /* BB enable after fixing up return data */ | ||
281 | |||
265 | #else | 282 | #else |
266 | cFYI(1,("query POSIX ACL not supported yet")); | 283 | cFYI(1,("query POSIX ACL not supported yet")); |
267 | #endif /* CONFIG_CIFS_POSIX */ | 284 | #endif /* CONFIG_CIFS_POSIX */ |
268 | } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 285 | } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT, |
286 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | ||
269 | #ifdef CONFIG_CIFS_POSIX | 287 | #ifdef CONFIG_CIFS_POSIX |
270 | if(sb->s_flags & MS_POSIXACL) | 288 | if(sb->s_flags & MS_POSIXACL) |
271 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 289 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |