diff options
| -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, |
