hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/cifs/smb1ops.c
....@@ -1,20 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * SMB1 (CIFS) version specific operations
34 *
45 * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
5
- *
6
- * This library is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License v2 as published
8
- * by the Free Software Foundation.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13
- * the GNU Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General Public License
16
- * along with this library; if not, write to the Free Software
17
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
186 */
197
208 #include <linux/pagemap.h>
....@@ -117,11 +105,11 @@
117105 }
118106
119107 static void
120
-cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add,
121
- const int optype)
108
+cifs_add_credits(struct TCP_Server_Info *server,
109
+ const struct cifs_credits *credits, const int optype)
122110 {
123111 spin_lock(&server->req_lock);
124
- server->credits += add;
112
+ server->credits += credits->value;
125113 server->in_flight--;
126114 spin_unlock(&server->req_lock);
127115 wake_up(&server->request_q);
....@@ -259,7 +247,7 @@
259247 /* check for plausible wct, bcc and t2 data and parm sizes */
260248 /* check for parm and data offset going beyond end of smb */
261249 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
262
- cifs_dbg(FYI, "invalid transact2 word count\n");
250
+ cifs_dbg(FYI, "Invalid transact2 word count\n");
263251 return -EINVAL;
264252 }
265253
....@@ -516,7 +504,8 @@
516504 }
517505
518506 static void
519
-cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
507
+cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
508
+ struct cifs_sb_info *cifs_sb)
520509 {
521510 CIFSSMBQFSDeviceInfo(xid, tcon);
522511 CIFSSMBQFSAttributeInfo(xid, tcon);
....@@ -577,7 +566,7 @@
577566 oparms.tcon = tcon;
578567 oparms.cifs_sb = cifs_sb;
579568 oparms.desired_access = FILE_READ_ATTRIBUTES;
580
- oparms.create_options = 0;
569
+ oparms.create_options = cifs_create_options(cifs_sb, 0);
581570 oparms.disposition = FILE_OPEN;
582571 oparms.path = full_path;
583572 oparms.fid = &fid;
....@@ -699,7 +688,7 @@
699688 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
700689 info.Attributes = cpu_to_le32(dosattrs);
701690 rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
702
- cifs_remap(cifs_sb));
691
+ cifs_sb);
703692 if (rc == 0)
704693 cifsInode->cifsAttrs = dosattrs;
705694 }
....@@ -777,7 +766,7 @@
777766 struct cifs_tcon *tcon;
778767
779768 /* if the file is already open for write, just use that fileid */
780
- open_file = find_writable_file(cinode, true);
769
+ open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
781770 if (open_file) {
782771 fid.netfid = open_file->fid.netfid;
783772 netpid = open_file->pid;
....@@ -794,7 +783,7 @@
794783 tcon = tlink_tcon(tlink);
795784
796785 rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls,
797
- cifs_remap(cifs_sb));
786
+ cifs_sb);
798787 if (rc == 0) {
799788 cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
800789 goto out;
....@@ -805,7 +794,7 @@
805794 oparms.tcon = tcon;
806795 oparms.cifs_sb = cifs_sb;
807796 oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES;
808
- oparms.create_options = CREATE_NOT_DIR;
797
+ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
809798 oparms.disposition = FILE_OPEN;
810799 oparms.path = full_path;
811800 oparms.fid = &fid;
....@@ -884,7 +873,7 @@
884873
885874 static int
886875 cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
887
- struct kstatfs *buf)
876
+ struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
888877 {
889878 int rc = -EOPNOTSUPP;
890879
....@@ -930,19 +919,18 @@
930919 {
931920 #ifdef CONFIG_CIFS_DFS_UPCALL
932921 int rc;
933
- unsigned int num_referrals = 0;
934
- struct dfs_info3_param *referrals = NULL;
922
+ struct dfs_info3_param referral = {0};
935923
936
- rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage,
937
- &num_referrals, &referrals, 0);
924
+ rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, &referral,
925
+ 0);
938926
939
- if (!rc && num_referrals > 0) {
940
- *symlinkinfo = kstrndup(referrals->node_name,
941
- strlen(referrals->node_name),
927
+ if (!rc) {
928
+ *symlinkinfo = kstrndup(referral.node_name,
929
+ strlen(referral.node_name),
942930 GFP_KERNEL);
931
+ free_dfs_info_param(&referral);
943932 if (!*symlinkinfo)
944933 rc = -ENOMEM;
945
- free_dfs_info_array(referrals, num_referrals);
946934 }
947935 return rc;
948936 #else /* No DFS support */
....@@ -952,8 +940,8 @@
952940
953941 static int
954942 cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
955
- const char *full_path, char **target_path,
956
- struct cifs_sb_info *cifs_sb)
943
+ struct cifs_sb_info *cifs_sb, const char *full_path,
944
+ char **target_path, bool is_reparse_point)
957945 {
958946 int rc;
959947 int oplock = 0;
....@@ -961,6 +949,11 @@
961949 struct cifs_open_parms oparms;
962950
963951 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
952
+
953
+ if (is_reparse_point) {
954
+ cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
955
+ return -EOPNOTSUPP;
956
+ }
964957
965958 /* Check for unix extensions */
966959 if (cap_unix(tcon->ses)) {
....@@ -978,7 +971,8 @@
978971 oparms.tcon = tcon;
979972 oparms.cifs_sb = cifs_sb;
980973 oparms.desired_access = FILE_READ_ATTRIBUTES;
981
- oparms.create_options = OPEN_REPARSE_POINT;
974
+ oparms.create_options = cifs_create_options(cifs_sb,
975
+ OPEN_REPARSE_POINT);
982976 oparms.disposition = FILE_OPEN;
983977 oparms.path = full_path;
984978 oparms.fid = &fid;
....@@ -1028,6 +1022,128 @@
10281022
10291023 return false;
10301024 }
1025
+
1026
+static int
1027
+cifs_make_node(unsigned int xid, struct inode *inode,
1028
+ struct dentry *dentry, struct cifs_tcon *tcon,
1029
+ char *full_path, umode_t mode, dev_t dev)
1030
+{
1031
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1032
+ struct inode *newinode = NULL;
1033
+ int rc = -EPERM;
1034
+ FILE_ALL_INFO *buf = NULL;
1035
+ struct cifs_io_parms io_parms;
1036
+ __u32 oplock = 0;
1037
+ struct cifs_fid fid;
1038
+ struct cifs_open_parms oparms;
1039
+ unsigned int bytes_written;
1040
+ struct win_dev *pdev;
1041
+ struct kvec iov[2];
1042
+
1043
+ if (tcon->unix_ext) {
1044
+ /*
1045
+ * SMB1 Unix Extensions: requires server support but
1046
+ * works with all special files
1047
+ */
1048
+ struct cifs_unix_set_info_args args = {
1049
+ .mode = mode & ~current_umask(),
1050
+ .ctime = NO_CHANGE_64,
1051
+ .atime = NO_CHANGE_64,
1052
+ .mtime = NO_CHANGE_64,
1053
+ .device = dev,
1054
+ };
1055
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1056
+ args.uid = current_fsuid();
1057
+ args.gid = current_fsgid();
1058
+ } else {
1059
+ args.uid = INVALID_UID; /* no change */
1060
+ args.gid = INVALID_GID; /* no change */
1061
+ }
1062
+ rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1063
+ cifs_sb->local_nls,
1064
+ cifs_remap(cifs_sb));
1065
+ if (rc)
1066
+ goto out;
1067
+
1068
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
1069
+ inode->i_sb, xid);
1070
+
1071
+ if (rc == 0)
1072
+ d_instantiate(dentry, newinode);
1073
+ goto out;
1074
+ }
1075
+
1076
+ /*
1077
+ * SMB1 SFU emulation: should work with all servers, but only
1078
+ * support block and char device (no socket & fifo)
1079
+ */
1080
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
1081
+ goto out;
1082
+
1083
+ if (!S_ISCHR(mode) && !S_ISBLK(mode))
1084
+ goto out;
1085
+
1086
+ cifs_dbg(FYI, "sfu compat create special file\n");
1087
+
1088
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
1089
+ if (buf == NULL) {
1090
+ rc = -ENOMEM;
1091
+ goto out;
1092
+ }
1093
+
1094
+ oparms.tcon = tcon;
1095
+ oparms.cifs_sb = cifs_sb;
1096
+ oparms.desired_access = GENERIC_WRITE;
1097
+ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
1098
+ CREATE_OPTION_SPECIAL);
1099
+ oparms.disposition = FILE_CREATE;
1100
+ oparms.path = full_path;
1101
+ oparms.fid = &fid;
1102
+ oparms.reconnect = false;
1103
+
1104
+ if (tcon->ses->server->oplocks)
1105
+ oplock = REQ_OPLOCK;
1106
+ else
1107
+ oplock = 0;
1108
+ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf);
1109
+ if (rc)
1110
+ goto out;
1111
+
1112
+ /*
1113
+ * BB Do not bother to decode buf since no local inode yet to put
1114
+ * timestamps in, but we can reuse it safely.
1115
+ */
1116
+
1117
+ pdev = (struct win_dev *)buf;
1118
+ io_parms.pid = current->tgid;
1119
+ io_parms.tcon = tcon;
1120
+ io_parms.offset = 0;
1121
+ io_parms.length = sizeof(struct win_dev);
1122
+ iov[1].iov_base = buf;
1123
+ iov[1].iov_len = sizeof(struct win_dev);
1124
+ if (S_ISCHR(mode)) {
1125
+ memcpy(pdev->type, "IntxCHR", 8);
1126
+ pdev->major = cpu_to_le64(MAJOR(dev));
1127
+ pdev->minor = cpu_to_le64(MINOR(dev));
1128
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
1129
+ &bytes_written, iov, 1);
1130
+ } else if (S_ISBLK(mode)) {
1131
+ memcpy(pdev->type, "IntxBLK", 8);
1132
+ pdev->major = cpu_to_le64(MAJOR(dev));
1133
+ pdev->minor = cpu_to_le64(MINOR(dev));
1134
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
1135
+ &bytes_written, iov, 1);
1136
+ }
1137
+ tcon->ses->server->ops->close(xid, tcon, &fid);
1138
+ d_drop(dentry);
1139
+
1140
+ /* FIXME: add code here to set EAs */
1141
+out:
1142
+ kfree(buf);
1143
+ return rc;
1144
+}
1145
+
1146
+
10311147
10321148 struct smb_version_operations smb1_operations = {
10331149 .send_cancel = send_nt_cancel,
....@@ -1107,15 +1223,15 @@
11071223 .query_all_EAs = CIFSSMBQAllEAs,
11081224 .set_EA = CIFSSMBSetEA,
11091225 #endif /* CIFS_XATTR */
1110
-#ifdef CONFIG_CIFS_ACL
11111226 .get_acl = get_cifs_acl,
11121227 .get_acl_by_fid = get_cifs_acl_by_fid,
11131228 .set_acl = set_cifs_acl,
1114
-#endif /* CIFS_ACL */
1229
+ .make_node = cifs_make_node,
11151230 };
11161231
11171232 struct smb_version_values smb1_values = {
11181233 .version_string = SMB1_VERSION_STRING,
1234
+ .protocol_id = SMB10_PROT_ID,
11191235 .large_lock_type = LOCKING_ANDX_LARGE_FILES,
11201236 .exclusive_lock_type = 0,
11211237 .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,