smb2inode.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. // SPDX-License-Identifier: LGPL-2.1
  2. /*
  3. *
  4. * Copyright (C) International Business Machines Corp., 2002, 2011
  5. * Etersoft, 2012
  6. * Author(s): Pavel Shilovsky (pshilovsky@samba.org),
  7. * Steve French (sfrench@us.ibm.com)
  8. *
  9. */
  10. #include <linux/fs.h>
  11. #include <linux/stat.h>
  12. #include <linux/slab.h>
  13. #include <linux/pagemap.h>
  14. #include <asm/div64.h>
  15. #include "cifsfs.h"
  16. #include "cifspdu.h"
  17. #include "cifsglob.h"
  18. #include "cifsproto.h"
  19. #include "cifs_debug.h"
  20. #include "cifs_fs_sb.h"
  21. #include "cifs_unicode.h"
  22. #include "fscache.h"
  23. #include "smb2glob.h"
  24. #include "smb2pdu.h"
  25. #include "smb2proto.h"
  26. #include "cached_dir.h"
  27. #include "../common/smb2status.h"
  28. static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
  29. {
  30. struct reparse_data_buffer *buf;
  31. struct smb2_ioctl_rsp *io = iov->iov_base;
  32. u32 off, count, len;
  33. count = le32_to_cpu(io->OutputCount);
  34. off = le32_to_cpu(io->OutputOffset);
  35. if (check_add_overflow(off, count, &len) || len > iov->iov_len)
  36. return ERR_PTR(-EIO);
  37. buf = (struct reparse_data_buffer *)((u8 *)io + off);
  38. len = sizeof(*buf);
  39. if (count < len || count < le16_to_cpu(buf->ReparseDataLength) + len)
  40. return ERR_PTR(-EIO);
  41. return buf;
  42. }
  43. static inline __u32 file_create_options(struct dentry *dentry)
  44. {
  45. struct cifsInodeInfo *ci;
  46. if (dentry) {
  47. ci = CIFS_I(d_inode(dentry));
  48. if (ci->cifsAttrs & ATTR_REPARSE)
  49. return OPEN_REPARSE_POINT;
  50. }
  51. return 0;
  52. }
  53. /* Parse owner and group from SMB3.1.1 POSIX query info */
  54. static int parse_posix_sids(struct cifs_open_info_data *data,
  55. struct kvec *rsp_iov)
  56. {
  57. struct smb2_query_info_rsp *qi = rsp_iov->iov_base;
  58. unsigned int out_len = le32_to_cpu(qi->OutputBufferLength);
  59. unsigned int qi_len = sizeof(data->posix_fi);
  60. int owner_len, group_len;
  61. u8 *sidsbuf, *sidsbuf_end;
  62. if (out_len <= qi_len)
  63. return -EINVAL;
  64. sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len;
  65. sidsbuf_end = sidsbuf + out_len - qi_len;
  66. owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
  67. if (owner_len == -1)
  68. return -EINVAL;
  69. memcpy(&data->posix_owner, sidsbuf, owner_len);
  70. group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end);
  71. if (group_len == -1)
  72. return -EINVAL;
  73. memcpy(&data->posix_group, sidsbuf + owner_len, group_len);
  74. return 0;
  75. }
  76. struct wsl_query_ea {
  77. __le32 next;
  78. __u8 name_len;
  79. __u8 name[SMB2_WSL_XATTR_NAME_LEN + 1];
  80. } __packed;
  81. #define NEXT_OFF cpu_to_le32(sizeof(struct wsl_query_ea))
  82. static const struct wsl_query_ea wsl_query_eas[] = {
  83. { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_UID, },
  84. { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_GID, },
  85. { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_MODE, },
  86. { .next = 0, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_DEV, },
  87. };
  88. static int check_wsl_eas(struct kvec *rsp_iov)
  89. {
  90. struct smb2_file_full_ea_info *ea;
  91. struct smb2_query_info_rsp *rsp = rsp_iov->iov_base;
  92. unsigned long addr;
  93. u32 outlen, next;
  94. u16 vlen;
  95. u8 nlen;
  96. u8 *end;
  97. outlen = le32_to_cpu(rsp->OutputBufferLength);
  98. if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE ||
  99. outlen > SMB2_WSL_MAX_QUERY_EA_RESP_SIZE)
  100. return -EINVAL;
  101. ea = (void *)((u8 *)rsp_iov->iov_base +
  102. le16_to_cpu(rsp->OutputBufferOffset));
  103. end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
  104. for (;;) {
  105. if ((u8 *)ea > end - sizeof(*ea))
  106. return -EINVAL;
  107. nlen = ea->ea_name_length;
  108. vlen = le16_to_cpu(ea->ea_value_length);
  109. if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
  110. (u8 *)ea + nlen + 1 + vlen > end)
  111. return -EINVAL;
  112. switch (vlen) {
  113. case 4:
  114. if (strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) &&
  115. strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) &&
  116. strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen))
  117. return -EINVAL;
  118. break;
  119. case 8:
  120. if (strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
  121. return -EINVAL;
  122. break;
  123. case 0:
  124. if (!strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) ||
  125. !strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) ||
  126. !strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen) ||
  127. !strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
  128. break;
  129. fallthrough;
  130. default:
  131. return -EINVAL;
  132. }
  133. next = le32_to_cpu(ea->next_entry_offset);
  134. if (!next)
  135. break;
  136. if (!IS_ALIGNED(next, 4) ||
  137. check_add_overflow((unsigned long)ea, next, &addr))
  138. return -EINVAL;
  139. ea = (void *)addr;
  140. }
  141. return 0;
  142. }
  143. /*
  144. * note: If cfile is passed, the reference to it is dropped here.
  145. * So make sure that you do not reuse cfile after return from this func.
  146. *
  147. * If passing @out_iov and @out_buftype, ensure to make them both large enough
  148. * (>= 3) to hold all compounded responses. Caller is also responsible for
  149. * freeing them up with free_rsp_buf().
  150. */
  151. static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
  152. struct cifs_sb_info *cifs_sb, const char *full_path,
  153. struct cifs_open_parms *oparms, struct kvec *in_iov,
  154. int *cmds, int num_cmds, struct cifsFileInfo *cfile,
  155. struct kvec *out_iov, int *out_buftype, struct dentry *dentry)
  156. {
  157. struct smb2_query_info_rsp *qi_rsp = NULL;
  158. struct smb2_compound_vars *vars = NULL;
  159. __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  160. struct cifs_open_info_data *idata;
  161. struct cifs_ses *ses = tcon->ses;
  162. struct reparse_data_buffer *rbuf;
  163. struct TCP_Server_Info *server;
  164. int resp_buftype[MAX_COMPOUND];
  165. int retries = 0, cur_sleep = 1;
  166. __u8 delete_pending[8] = {1,};
  167. struct kvec *rsp_iov, *iov;
  168. struct inode *inode = NULL;
  169. __le16 *utf16_path = NULL;
  170. struct smb_rqst *rqst;
  171. unsigned int size[2];
  172. struct cifs_fid fid;
  173. int num_rqst = 0, i;
  174. unsigned int len;
  175. int tmp_rc, rc;
  176. int flags = 0;
  177. void *data[2];
  178. replay_again:
  179. /* reinitialize for possible replay */
  180. flags = 0;
  181. oplock = SMB2_OPLOCK_LEVEL_NONE;
  182. num_rqst = 0;
  183. server = cifs_pick_channel(ses);
  184. vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
  185. if (vars == NULL) {
  186. rc = -ENOMEM;
  187. goto out;
  188. }
  189. rqst = &vars->rqst[0];
  190. rsp_iov = &vars->rsp_iov[0];
  191. if (smb3_encryption_required(tcon))
  192. flags |= CIFS_TRANSFORM_REQ;
  193. for (i = 0; i < ARRAY_SIZE(resp_buftype); i++)
  194. resp_buftype[i] = CIFS_NO_BUFFER;
  195. /* We already have a handle so we can skip the open */
  196. if (cfile)
  197. goto after_open;
  198. /* Open */
  199. utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  200. if (!utf16_path) {
  201. rc = -ENOMEM;
  202. goto finished;
  203. }
  204. /* if there is an existing lease, reuse it */
  205. /*
  206. * note: files with hardlinks cause unexpected behaviour. As per MS-SMB2,
  207. * lease keys are associated with the filepath. We are maintaining lease keys
  208. * with the inode on the client. If the file has hardlinks, it is possible
  209. * that the lease for a file be reused for an operation on its hardlink or
  210. * vice versa.
  211. * As a workaround, send request using an existing lease key and if the server
  212. * returns STATUS_INVALID_PARAMETER, which maps to EINVAL, send the request
  213. * again without the lease.
  214. */
  215. if (dentry) {
  216. inode = d_inode(dentry);
  217. if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) {
  218. oplock = SMB2_OPLOCK_LEVEL_LEASE;
  219. server->ops->get_lease_key(inode, &fid);
  220. }
  221. }
  222. vars->oparms = *oparms;
  223. vars->oparms.fid = &fid;
  224. rqst[num_rqst].rq_iov = &vars->open_iov[0];
  225. rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
  226. rc = SMB2_open_init(tcon, server,
  227. &rqst[num_rqst], &oplock, &vars->oparms,
  228. utf16_path);
  229. kfree(utf16_path);
  230. if (rc)
  231. goto finished;
  232. smb2_set_next_command(tcon, &rqst[num_rqst]);
  233. after_open:
  234. num_rqst++;
  235. rc = 0;
  236. for (i = 0; i < num_cmds; i++) {
  237. /* Operation */
  238. switch (cmds[i]) {
  239. case SMB2_OP_QUERY_INFO:
  240. rqst[num_rqst].rq_iov = &vars->qi_iov;
  241. rqst[num_rqst].rq_nvec = 1;
  242. if (cfile) {
  243. rc = SMB2_query_info_init(tcon, server,
  244. &rqst[num_rqst],
  245. cfile->fid.persistent_fid,
  246. cfile->fid.volatile_fid,
  247. FILE_ALL_INFORMATION,
  248. SMB2_O_INFO_FILE, 0,
  249. sizeof(struct smb2_file_all_info) +
  250. PATH_MAX * 2, 0, NULL);
  251. } else {
  252. rc = SMB2_query_info_init(tcon, server,
  253. &rqst[num_rqst],
  254. COMPOUND_FID,
  255. COMPOUND_FID,
  256. FILE_ALL_INFORMATION,
  257. SMB2_O_INFO_FILE, 0,
  258. sizeof(struct smb2_file_all_info) +
  259. PATH_MAX * 2, 0, NULL);
  260. }
  261. if (!rc && (!cfile || num_rqst > 1)) {
  262. smb2_set_next_command(tcon, &rqst[num_rqst]);
  263. smb2_set_related(&rqst[num_rqst]);
  264. } else if (rc) {
  265. goto finished;
  266. }
  267. num_rqst++;
  268. trace_smb3_query_info_compound_enter(xid, tcon->tid,
  269. ses->Suid, full_path);
  270. break;
  271. case SMB2_OP_POSIX_QUERY_INFO:
  272. rqst[num_rqst].rq_iov = &vars->qi_iov;
  273. rqst[num_rqst].rq_nvec = 1;
  274. if (cfile) {
  275. /* TBD: fix following to allow for longer SIDs */
  276. rc = SMB2_query_info_init(tcon, server,
  277. &rqst[num_rqst],
  278. cfile->fid.persistent_fid,
  279. cfile->fid.volatile_fid,
  280. SMB_FIND_FILE_POSIX_INFO,
  281. SMB2_O_INFO_FILE, 0,
  282. sizeof(struct smb311_posix_qinfo *) +
  283. (PATH_MAX * 2) +
  284. (sizeof(struct smb_sid) * 2), 0, NULL);
  285. } else {
  286. rc = SMB2_query_info_init(tcon, server,
  287. &rqst[num_rqst],
  288. COMPOUND_FID,
  289. COMPOUND_FID,
  290. SMB_FIND_FILE_POSIX_INFO,
  291. SMB2_O_INFO_FILE, 0,
  292. sizeof(struct smb311_posix_qinfo *) +
  293. (PATH_MAX * 2) +
  294. (sizeof(struct smb_sid) * 2), 0, NULL);
  295. }
  296. if (!rc && (!cfile || num_rqst > 1)) {
  297. smb2_set_next_command(tcon, &rqst[num_rqst]);
  298. smb2_set_related(&rqst[num_rqst]);
  299. } else if (rc) {
  300. goto finished;
  301. }
  302. num_rqst++;
  303. trace_smb3_posix_query_info_compound_enter(xid, tcon->tid,
  304. ses->Suid, full_path);
  305. break;
  306. case SMB2_OP_DELETE:
  307. trace_smb3_delete_enter(xid, tcon->tid, ses->Suid, full_path);
  308. break;
  309. case SMB2_OP_MKDIR:
  310. /*
  311. * Directories are created through parameters in the
  312. * SMB2_open() call.
  313. */
  314. trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path);
  315. break;
  316. case SMB2_OP_RMDIR:
  317. rqst[num_rqst].rq_iov = &vars->si_iov[0];
  318. rqst[num_rqst].rq_nvec = 1;
  319. size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
  320. data[0] = &delete_pending[0];
  321. rc = SMB2_set_info_init(tcon, server,
  322. &rqst[num_rqst], COMPOUND_FID,
  323. COMPOUND_FID, current->tgid,
  324. FILE_DISPOSITION_INFORMATION,
  325. SMB2_O_INFO_FILE, 0, data, size);
  326. if (rc)
  327. goto finished;
  328. smb2_set_next_command(tcon, &rqst[num_rqst]);
  329. smb2_set_related(&rqst[num_rqst++]);
  330. trace_smb3_rmdir_enter(xid, tcon->tid, ses->Suid, full_path);
  331. break;
  332. case SMB2_OP_SET_EOF:
  333. rqst[num_rqst].rq_iov = &vars->si_iov[0];
  334. rqst[num_rqst].rq_nvec = 1;
  335. size[0] = in_iov[i].iov_len;
  336. data[0] = in_iov[i].iov_base;
  337. if (cfile) {
  338. rc = SMB2_set_info_init(tcon, server,
  339. &rqst[num_rqst],
  340. cfile->fid.persistent_fid,
  341. cfile->fid.volatile_fid,
  342. current->tgid,
  343. FILE_END_OF_FILE_INFORMATION,
  344. SMB2_O_INFO_FILE, 0,
  345. data, size);
  346. } else {
  347. rc = SMB2_set_info_init(tcon, server,
  348. &rqst[num_rqst],
  349. COMPOUND_FID,
  350. COMPOUND_FID,
  351. current->tgid,
  352. FILE_END_OF_FILE_INFORMATION,
  353. SMB2_O_INFO_FILE, 0,
  354. data, size);
  355. }
  356. if (!rc && (!cfile || num_rqst > 1)) {
  357. smb2_set_next_command(tcon, &rqst[num_rqst]);
  358. smb2_set_related(&rqst[num_rqst]);
  359. } else if (rc) {
  360. goto finished;
  361. }
  362. num_rqst++;
  363. trace_smb3_set_eof_enter(xid, tcon->tid, ses->Suid, full_path);
  364. break;
  365. case SMB2_OP_SET_INFO:
  366. rqst[num_rqst].rq_iov = &vars->si_iov[0];
  367. rqst[num_rqst].rq_nvec = 1;
  368. size[0] = in_iov[i].iov_len;
  369. data[0] = in_iov[i].iov_base;
  370. if (cfile) {
  371. rc = SMB2_set_info_init(tcon, server,
  372. &rqst[num_rqst],
  373. cfile->fid.persistent_fid,
  374. cfile->fid.volatile_fid, current->tgid,
  375. FILE_BASIC_INFORMATION,
  376. SMB2_O_INFO_FILE, 0, data, size);
  377. } else {
  378. rc = SMB2_set_info_init(tcon, server,
  379. &rqst[num_rqst],
  380. COMPOUND_FID,
  381. COMPOUND_FID, current->tgid,
  382. FILE_BASIC_INFORMATION,
  383. SMB2_O_INFO_FILE, 0, data, size);
  384. }
  385. if (!rc && (!cfile || num_rqst > 1)) {
  386. smb2_set_next_command(tcon, &rqst[num_rqst]);
  387. smb2_set_related(&rqst[num_rqst]);
  388. } else if (rc) {
  389. goto finished;
  390. }
  391. num_rqst++;
  392. trace_smb3_set_info_compound_enter(xid, tcon->tid,
  393. ses->Suid, full_path);
  394. break;
  395. case SMB2_OP_RENAME:
  396. rqst[num_rqst].rq_iov = &vars->si_iov[0];
  397. rqst[num_rqst].rq_nvec = 2;
  398. len = in_iov[i].iov_len;
  399. vars->rename_info.ReplaceIfExists = 1;
  400. vars->rename_info.RootDirectory = 0;
  401. vars->rename_info.FileNameLength = cpu_to_le32(len);
  402. size[0] = sizeof(struct smb2_file_rename_info);
  403. data[0] = &vars->rename_info;
  404. size[1] = len + 2 /* null */;
  405. data[1] = in_iov[i].iov_base;
  406. if (cfile) {
  407. rc = SMB2_set_info_init(tcon, server,
  408. &rqst[num_rqst],
  409. cfile->fid.persistent_fid,
  410. cfile->fid.volatile_fid,
  411. current->tgid, FILE_RENAME_INFORMATION,
  412. SMB2_O_INFO_FILE, 0, data, size);
  413. } else {
  414. rc = SMB2_set_info_init(tcon, server,
  415. &rqst[num_rqst],
  416. COMPOUND_FID, COMPOUND_FID,
  417. current->tgid, FILE_RENAME_INFORMATION,
  418. SMB2_O_INFO_FILE, 0, data, size);
  419. }
  420. if (!rc && (!cfile || num_rqst > 1)) {
  421. smb2_set_next_command(tcon, &rqst[num_rqst]);
  422. smb2_set_related(&rqst[num_rqst]);
  423. } else if (rc) {
  424. goto finished;
  425. }
  426. num_rqst++;
  427. trace_smb3_rename_enter(xid, tcon->tid, ses->Suid, full_path);
  428. break;
  429. case SMB2_OP_HARDLINK:
  430. rqst[num_rqst].rq_iov = &vars->si_iov[0];
  431. rqst[num_rqst].rq_nvec = 2;
  432. len = in_iov[i].iov_len;
  433. vars->link_info.ReplaceIfExists = 0;
  434. vars->link_info.RootDirectory = 0;
  435. vars->link_info.FileNameLength = cpu_to_le32(len);
  436. size[0] = sizeof(struct smb2_file_link_info);
  437. data[0] = &vars->link_info;
  438. size[1] = len + 2 /* null */;
  439. data[1] = in_iov[i].iov_base;
  440. rc = SMB2_set_info_init(tcon, server,
  441. &rqst[num_rqst], COMPOUND_FID,
  442. COMPOUND_FID, current->tgid,
  443. FILE_LINK_INFORMATION,
  444. SMB2_O_INFO_FILE, 0, data, size);
  445. if (rc)
  446. goto finished;
  447. smb2_set_next_command(tcon, &rqst[num_rqst]);
  448. smb2_set_related(&rqst[num_rqst++]);
  449. trace_smb3_hardlink_enter(xid, tcon->tid, ses->Suid, full_path);
  450. break;
  451. case SMB2_OP_SET_REPARSE:
  452. rqst[num_rqst].rq_iov = vars->io_iov;
  453. rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
  454. if (cfile) {
  455. rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
  456. cfile->fid.persistent_fid,
  457. cfile->fid.volatile_fid,
  458. FSCTL_SET_REPARSE_POINT,
  459. in_iov[i].iov_base,
  460. in_iov[i].iov_len, 0);
  461. } else {
  462. rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
  463. COMPOUND_FID, COMPOUND_FID,
  464. FSCTL_SET_REPARSE_POINT,
  465. in_iov[i].iov_base,
  466. in_iov[i].iov_len, 0);
  467. }
  468. if (!rc && (!cfile || num_rqst > 1)) {
  469. smb2_set_next_command(tcon, &rqst[num_rqst]);
  470. smb2_set_related(&rqst[num_rqst]);
  471. } else if (rc) {
  472. goto finished;
  473. }
  474. num_rqst++;
  475. trace_smb3_set_reparse_compound_enter(xid, tcon->tid,
  476. ses->Suid, full_path);
  477. break;
  478. case SMB2_OP_GET_REPARSE:
  479. rqst[num_rqst].rq_iov = vars->io_iov;
  480. rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
  481. if (cfile) {
  482. rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
  483. cfile->fid.persistent_fid,
  484. cfile->fid.volatile_fid,
  485. FSCTL_GET_REPARSE_POINT,
  486. NULL, 0, CIFSMaxBufSize);
  487. } else {
  488. rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
  489. COMPOUND_FID, COMPOUND_FID,
  490. FSCTL_GET_REPARSE_POINT,
  491. NULL, 0, CIFSMaxBufSize);
  492. }
  493. if (!rc && (!cfile || num_rqst > 1)) {
  494. smb2_set_next_command(tcon, &rqst[num_rqst]);
  495. smb2_set_related(&rqst[num_rqst]);
  496. } else if (rc) {
  497. goto finished;
  498. }
  499. num_rqst++;
  500. trace_smb3_get_reparse_compound_enter(xid, tcon->tid,
  501. ses->Suid, full_path);
  502. break;
  503. case SMB2_OP_QUERY_WSL_EA:
  504. rqst[num_rqst].rq_iov = &vars->ea_iov;
  505. rqst[num_rqst].rq_nvec = 1;
  506. if (cfile) {
  507. rc = SMB2_query_info_init(tcon, server,
  508. &rqst[num_rqst],
  509. cfile->fid.persistent_fid,
  510. cfile->fid.volatile_fid,
  511. FILE_FULL_EA_INFORMATION,
  512. SMB2_O_INFO_FILE, 0,
  513. SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
  514. sizeof(wsl_query_eas),
  515. (void *)wsl_query_eas);
  516. } else {
  517. rc = SMB2_query_info_init(tcon, server,
  518. &rqst[num_rqst],
  519. COMPOUND_FID,
  520. COMPOUND_FID,
  521. FILE_FULL_EA_INFORMATION,
  522. SMB2_O_INFO_FILE, 0,
  523. SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
  524. sizeof(wsl_query_eas),
  525. (void *)wsl_query_eas);
  526. }
  527. if (!rc && (!cfile || num_rqst > 1)) {
  528. smb2_set_next_command(tcon, &rqst[num_rqst]);
  529. smb2_set_related(&rqst[num_rqst]);
  530. } else if (rc) {
  531. goto finished;
  532. }
  533. num_rqst++;
  534. break;
  535. default:
  536. cifs_dbg(VFS, "Invalid command\n");
  537. rc = -EINVAL;
  538. }
  539. }
  540. if (rc)
  541. goto finished;
  542. /* We already have a handle so we can skip the close */
  543. if (cfile)
  544. goto after_close;
  545. /* Close */
  546. flags |= CIFS_CP_CREATE_CLOSE_OP;
  547. rqst[num_rqst].rq_iov = &vars->close_iov;
  548. rqst[num_rqst].rq_nvec = 1;
  549. rc = SMB2_close_init(tcon, server,
  550. &rqst[num_rqst], COMPOUND_FID,
  551. COMPOUND_FID, false);
  552. smb2_set_related(&rqst[num_rqst]);
  553. if (rc)
  554. goto finished;
  555. after_close:
  556. num_rqst++;
  557. if (cfile) {
  558. if (retries)
  559. for (i = 1; i < num_rqst - 2; i++)
  560. smb2_set_replay(server, &rqst[i]);
  561. rc = compound_send_recv(xid, ses, server,
  562. flags, num_rqst - 2,
  563. &rqst[1], &resp_buftype[1],
  564. &rsp_iov[1]);
  565. } else {
  566. if (retries)
  567. for (i = 0; i < num_rqst; i++)
  568. smb2_set_replay(server, &rqst[i]);
  569. rc = compound_send_recv(xid, ses, server,
  570. flags, num_rqst,
  571. rqst, resp_buftype,
  572. rsp_iov);
  573. }
  574. finished:
  575. num_rqst = 0;
  576. SMB2_open_free(&rqst[num_rqst++]);
  577. if (rc == -EREMCHG) {
  578. pr_warn_once("server share %s deleted\n", tcon->tree_name);
  579. tcon->need_reconnect = true;
  580. }
  581. tmp_rc = rc;
  582. for (i = 0; i < num_cmds; i++) {
  583. char *buf = rsp_iov[i + 1].iov_base;
  584. if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER)
  585. rc = server->ops->map_error(buf, false);
  586. else
  587. rc = tmp_rc;
  588. switch (cmds[i]) {
  589. case SMB2_OP_QUERY_INFO:
  590. idata = in_iov[i].iov_base;
  591. idata->contains_posix_file_info = false;
  592. if (rc == 0 && cfile && cfile->symlink_target) {
  593. idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
  594. if (!idata->symlink_target)
  595. rc = -ENOMEM;
  596. }
  597. if (rc == 0) {
  598. qi_rsp = (struct smb2_query_info_rsp *)
  599. rsp_iov[i + 1].iov_base;
  600. rc = smb2_validate_and_copy_iov(
  601. le16_to_cpu(qi_rsp->OutputBufferOffset),
  602. le32_to_cpu(qi_rsp->OutputBufferLength),
  603. &rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi);
  604. }
  605. SMB2_query_info_free(&rqst[num_rqst++]);
  606. if (rc)
  607. trace_smb3_query_info_compound_err(xid, tcon->tid,
  608. ses->Suid, rc);
  609. else
  610. trace_smb3_query_info_compound_done(xid, tcon->tid,
  611. ses->Suid);
  612. break;
  613. case SMB2_OP_POSIX_QUERY_INFO:
  614. idata = in_iov[i].iov_base;
  615. idata->contains_posix_file_info = true;
  616. if (rc == 0 && cfile && cfile->symlink_target) {
  617. idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
  618. if (!idata->symlink_target)
  619. rc = -ENOMEM;
  620. }
  621. if (rc == 0) {
  622. qi_rsp = (struct smb2_query_info_rsp *)
  623. rsp_iov[i + 1].iov_base;
  624. rc = smb2_validate_and_copy_iov(
  625. le16_to_cpu(qi_rsp->OutputBufferOffset),
  626. le32_to_cpu(qi_rsp->OutputBufferLength),
  627. &rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
  628. (char *)&idata->posix_fi);
  629. }
  630. if (rc == 0)
  631. rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
  632. SMB2_query_info_free(&rqst[num_rqst++]);
  633. if (rc)
  634. trace_smb3_posix_query_info_compound_err(xid, tcon->tid,
  635. ses->Suid, rc);
  636. else
  637. trace_smb3_posix_query_info_compound_done(xid, tcon->tid,
  638. ses->Suid);
  639. break;
  640. case SMB2_OP_DELETE:
  641. if (rc)
  642. trace_smb3_delete_err(xid, tcon->tid, ses->Suid, rc);
  643. else {
  644. /*
  645. * If dentry (hence, inode) is NULL, lease break is going to
  646. * take care of degrading leases on handles for deleted files.
  647. */
  648. if (inode)
  649. cifs_mark_open_handles_for_deleted_file(inode, full_path);
  650. trace_smb3_delete_done(xid, tcon->tid, ses->Suid);
  651. }
  652. break;
  653. case SMB2_OP_MKDIR:
  654. if (rc)
  655. trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc);
  656. else
  657. trace_smb3_mkdir_done(xid, tcon->tid, ses->Suid);
  658. break;
  659. case SMB2_OP_HARDLINK:
  660. if (rc)
  661. trace_smb3_hardlink_err(xid, tcon->tid, ses->Suid, rc);
  662. else
  663. trace_smb3_hardlink_done(xid, tcon->tid, ses->Suid);
  664. SMB2_set_info_free(&rqst[num_rqst++]);
  665. break;
  666. case SMB2_OP_RENAME:
  667. if (rc)
  668. trace_smb3_rename_err(xid, tcon->tid, ses->Suid, rc);
  669. else
  670. trace_smb3_rename_done(xid, tcon->tid, ses->Suid);
  671. SMB2_set_info_free(&rqst[num_rqst++]);
  672. break;
  673. case SMB2_OP_RMDIR:
  674. if (rc)
  675. trace_smb3_rmdir_err(xid, tcon->tid, ses->Suid, rc);
  676. else
  677. trace_smb3_rmdir_done(xid, tcon->tid, ses->Suid);
  678. SMB2_set_info_free(&rqst[num_rqst++]);
  679. break;
  680. case SMB2_OP_SET_EOF:
  681. if (rc)
  682. trace_smb3_set_eof_err(xid, tcon->tid, ses->Suid, rc);
  683. else
  684. trace_smb3_set_eof_done(xid, tcon->tid, ses->Suid);
  685. SMB2_set_info_free(&rqst[num_rqst++]);
  686. break;
  687. case SMB2_OP_SET_INFO:
  688. if (rc)
  689. trace_smb3_set_info_compound_err(xid, tcon->tid,
  690. ses->Suid, rc);
  691. else
  692. trace_smb3_set_info_compound_done(xid, tcon->tid,
  693. ses->Suid);
  694. SMB2_set_info_free(&rqst[num_rqst++]);
  695. break;
  696. case SMB2_OP_SET_REPARSE:
  697. if (rc) {
  698. trace_smb3_set_reparse_compound_err(xid, tcon->tid,
  699. ses->Suid, rc);
  700. } else {
  701. trace_smb3_set_reparse_compound_done(xid, tcon->tid,
  702. ses->Suid);
  703. }
  704. SMB2_ioctl_free(&rqst[num_rqst++]);
  705. break;
  706. case SMB2_OP_GET_REPARSE:
  707. if (!rc) {
  708. iov = &rsp_iov[i + 1];
  709. idata = in_iov[i].iov_base;
  710. idata->reparse.io.iov = *iov;
  711. idata->reparse.io.buftype = resp_buftype[i + 1];
  712. idata->contains_posix_file_info = false; /* BB VERIFY */
  713. rbuf = reparse_buf_ptr(iov);
  714. if (IS_ERR(rbuf)) {
  715. rc = PTR_ERR(rbuf);
  716. trace_smb3_get_reparse_compound_err(xid, tcon->tid,
  717. ses->Suid, rc);
  718. } else {
  719. idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag);
  720. trace_smb3_get_reparse_compound_done(xid, tcon->tid,
  721. ses->Suid);
  722. }
  723. memset(iov, 0, sizeof(*iov));
  724. resp_buftype[i + 1] = CIFS_NO_BUFFER;
  725. } else {
  726. trace_smb3_get_reparse_compound_err(xid, tcon->tid,
  727. ses->Suid, rc);
  728. }
  729. SMB2_ioctl_free(&rqst[num_rqst++]);
  730. break;
  731. case SMB2_OP_QUERY_WSL_EA:
  732. if (!rc) {
  733. idata = in_iov[i].iov_base;
  734. idata->contains_posix_file_info = false;
  735. qi_rsp = rsp_iov[i + 1].iov_base;
  736. data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
  737. size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
  738. rc = check_wsl_eas(&rsp_iov[i + 1]);
  739. if (!rc) {
  740. memcpy(idata->wsl.eas, data[0], size[0]);
  741. idata->wsl.eas_len = size[0];
  742. }
  743. }
  744. if (!rc) {
  745. trace_smb3_query_wsl_ea_compound_done(xid, tcon->tid,
  746. ses->Suid);
  747. } else {
  748. trace_smb3_query_wsl_ea_compound_err(xid, tcon->tid,
  749. ses->Suid, rc);
  750. }
  751. SMB2_query_info_free(&rqst[num_rqst++]);
  752. break;
  753. }
  754. }
  755. SMB2_close_free(&rqst[num_rqst]);
  756. rc = tmp_rc;
  757. num_cmds += 2;
  758. if (out_iov && out_buftype) {
  759. memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov));
  760. memcpy(out_buftype, resp_buftype,
  761. num_cmds * sizeof(*out_buftype));
  762. } else {
  763. for (i = 0; i < num_cmds; i++)
  764. free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base);
  765. }
  766. num_cmds -= 2; /* correct num_cmds as there could be a retry */
  767. kfree(vars);
  768. if (is_replayable_error(rc) &&
  769. smb2_should_replay(tcon, &retries, &cur_sleep))
  770. goto replay_again;
  771. out:
  772. if (cfile)
  773. cifsFileInfo_put(cfile);
  774. return rc;
  775. }
  776. static int parse_create_response(struct cifs_open_info_data *data,
  777. struct cifs_sb_info *cifs_sb,
  778. const char *full_path,
  779. const struct kvec *iov)
  780. {
  781. struct smb2_create_rsp *rsp = iov->iov_base;
  782. bool reparse_point = false;
  783. u32 tag = 0;
  784. int rc = 0;
  785. switch (rsp->hdr.Status) {
  786. case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
  787. reparse_point = true;
  788. break;
  789. case STATUS_STOPPED_ON_SYMLINK:
  790. rc = smb2_parse_symlink_response(cifs_sb, iov,
  791. full_path,
  792. &data->symlink_target);
  793. if (rc)
  794. return rc;
  795. tag = IO_REPARSE_TAG_SYMLINK;
  796. reparse_point = true;
  797. break;
  798. case STATUS_SUCCESS:
  799. reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
  800. break;
  801. }
  802. data->reparse_point = reparse_point;
  803. data->reparse.tag = tag;
  804. return rc;
  805. }
  806. /* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */
  807. static bool ea_unsupported(int *cmds, int num_cmds,
  808. struct kvec *out_iov, int *out_buftype)
  809. {
  810. int i;
  811. if (cmds[num_cmds - 1] != SMB2_OP_QUERY_WSL_EA)
  812. return false;
  813. for (i = 1; i < num_cmds - 1; i++) {
  814. struct smb2_hdr *hdr = out_iov[i].iov_base;
  815. if (out_buftype[i] == CIFS_NO_BUFFER || !hdr ||
  816. hdr->Status != STATUS_SUCCESS)
  817. return false;
  818. }
  819. return true;
  820. }
  821. static inline void free_rsp_iov(struct kvec *iovs, int *buftype, int count)
  822. {
  823. int i;
  824. for (i = 0; i < count; i++) {
  825. free_rsp_buf(buftype[i], iovs[i].iov_base);
  826. memset(&iovs[i], 0, sizeof(*iovs));
  827. buftype[i] = CIFS_NO_BUFFER;
  828. }
  829. }
  830. int smb2_query_path_info(const unsigned int xid,
  831. struct cifs_tcon *tcon,
  832. struct cifs_sb_info *cifs_sb,
  833. const char *full_path,
  834. struct cifs_open_info_data *data)
  835. {
  836. struct kvec in_iov[3], out_iov[5] = {};
  837. struct cached_fid *cfid = NULL;
  838. struct cifs_open_parms oparms;
  839. struct cifsFileInfo *cfile;
  840. __u32 create_options = 0;
  841. int out_buftype[5] = {};
  842. struct smb2_hdr *hdr;
  843. int num_cmds = 0;
  844. int cmds[3];
  845. bool islink;
  846. int rc, rc2;
  847. data->adjust_tz = false;
  848. data->reparse_point = false;
  849. /*
  850. * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
  851. * Create SMB2_query_posix_info worker function to do non-compounded
  852. * query when we already have an open file handle for this. For now this
  853. * is fast enough (always using the compounded version).
  854. */
  855. if (!tcon->posix_extensions) {
  856. if (*full_path) {
  857. rc = -ENOENT;
  858. } else {
  859. rc = open_cached_dir(xid, tcon, full_path,
  860. cifs_sb, false, &cfid);
  861. }
  862. /* If it is a root and its handle is cached then use it */
  863. if (!rc) {
  864. if (cfid->file_all_info_is_valid) {
  865. memcpy(&data->fi, &cfid->file_all_info,
  866. sizeof(data->fi));
  867. } else {
  868. rc = SMB2_query_info(xid, tcon,
  869. cfid->fid.persistent_fid,
  870. cfid->fid.volatile_fid,
  871. &data->fi);
  872. }
  873. close_cached_dir(cfid);
  874. return rc;
  875. }
  876. cmds[num_cmds++] = SMB2_OP_QUERY_INFO;
  877. } else {
  878. cmds[num_cmds++] = SMB2_OP_POSIX_QUERY_INFO;
  879. }
  880. in_iov[0].iov_base = data;
  881. in_iov[0].iov_len = sizeof(*data);
  882. in_iov[1] = in_iov[0];
  883. in_iov[2] = in_iov[0];
  884. cifs_get_readable_path(tcon, full_path, &cfile);
  885. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES,
  886. FILE_OPEN, create_options, ACL_NO_MODE);
  887. rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
  888. &oparms, in_iov, cmds, num_cmds,
  889. cfile, out_iov, out_buftype, NULL);
  890. hdr = out_iov[0].iov_base;
  891. /*
  892. * If first iov is unset, then SMB session was dropped or we've got a
  893. * cached open file (@cfile).
  894. */
  895. if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
  896. goto out;
  897. switch (rc) {
  898. case 0:
  899. rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
  900. break;
  901. case -EOPNOTSUPP:
  902. /*
  903. * BB TODO: When support for special files added to Samba
  904. * re-verify this path.
  905. */
  906. rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
  907. if (rc || !data->reparse_point)
  908. goto out;
  909. /*
  910. * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
  911. * response.
  912. */
  913. if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK)
  914. cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
  915. if (!tcon->posix_extensions)
  916. cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
  917. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
  918. FILE_READ_ATTRIBUTES |
  919. FILE_READ_EA | SYNCHRONIZE,
  920. FILE_OPEN, create_options |
  921. OPEN_REPARSE_POINT, ACL_NO_MODE);
  922. cifs_get_readable_path(tcon, full_path, &cfile);
  923. free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
  924. rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
  925. &oparms, in_iov, cmds, num_cmds,
  926. cfile, out_iov, out_buftype, NULL);
  927. if (rc && ea_unsupported(cmds, num_cmds,
  928. out_iov, out_buftype)) {
  929. if (data->reparse.tag != IO_REPARSE_TAG_LX_BLK &&
  930. data->reparse.tag != IO_REPARSE_TAG_LX_CHR)
  931. rc = 0;
  932. else
  933. rc = -EOPNOTSUPP;
  934. }
  935. break;
  936. case -EREMOTE:
  937. break;
  938. default:
  939. if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
  940. break;
  941. rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
  942. full_path, &islink);
  943. if (rc2) {
  944. rc = rc2;
  945. goto out;
  946. }
  947. if (islink)
  948. rc = -EREMOTE;
  949. }
  950. out:
  951. free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
  952. return rc;
  953. }
  954. int
  955. smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
  956. struct cifs_tcon *tcon, const char *name,
  957. struct cifs_sb_info *cifs_sb)
  958. {
  959. struct cifs_open_parms oparms;
  960. oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
  961. FILE_CREATE, CREATE_NOT_FILE, mode);
  962. return smb2_compound_op(xid, tcon, cifs_sb,
  963. name, &oparms, NULL,
  964. &(int){SMB2_OP_MKDIR}, 1,
  965. NULL, NULL, NULL, NULL);
  966. }
  967. void
  968. smb2_mkdir_setinfo(struct inode *inode, const char *name,
  969. struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
  970. const unsigned int xid)
  971. {
  972. struct cifs_open_parms oparms;
  973. FILE_BASIC_INFO data = {};
  974. struct cifsInodeInfo *cifs_i;
  975. struct cifsFileInfo *cfile;
  976. struct kvec in_iov;
  977. u32 dosattrs;
  978. int tmprc;
  979. in_iov.iov_base = &data;
  980. in_iov.iov_len = sizeof(data);
  981. cifs_i = CIFS_I(inode);
  982. dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
  983. data.Attributes = cpu_to_le32(dosattrs);
  984. cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
  985. oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
  986. FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
  987. tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
  988. &oparms, &in_iov,
  989. &(int){SMB2_OP_SET_INFO}, 1,
  990. cfile, NULL, NULL, NULL);
  991. if (tmprc == 0)
  992. cifs_i->cifsAttrs = dosattrs;
  993. }
  994. int
  995. smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  996. struct cifs_sb_info *cifs_sb)
  997. {
  998. struct cifs_open_parms oparms;
  999. drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
  1000. oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE,
  1001. FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE);
  1002. return smb2_compound_op(xid, tcon, cifs_sb,
  1003. name, &oparms, NULL,
  1004. &(int){SMB2_OP_RMDIR}, 1,
  1005. NULL, NULL, NULL, NULL);
  1006. }
  1007. int
  1008. smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  1009. struct cifs_sb_info *cifs_sb, struct dentry *dentry)
  1010. {
  1011. struct cifs_open_parms oparms;
  1012. oparms = CIFS_OPARMS(cifs_sb, tcon, name,
  1013. DELETE, FILE_OPEN,
  1014. CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
  1015. ACL_NO_MODE);
  1016. int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms,
  1017. NULL, &(int){SMB2_OP_DELETE}, 1,
  1018. NULL, NULL, NULL, dentry);
  1019. if (rc == -EINVAL) {
  1020. cifs_dbg(FYI, "invalid lease key, resending request without lease");
  1021. rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms,
  1022. NULL, &(int){SMB2_OP_DELETE}, 1,
  1023. NULL, NULL, NULL, NULL);
  1024. }
  1025. return rc;
  1026. }
  1027. static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
  1028. const char *from_name, const char *to_name,
  1029. struct cifs_sb_info *cifs_sb,
  1030. __u32 create_options, __u32 access,
  1031. int command, struct cifsFileInfo *cfile,
  1032. struct dentry *dentry)
  1033. {
  1034. struct cifs_open_parms oparms;
  1035. struct kvec in_iov;
  1036. __le16 *smb2_to_name = NULL;
  1037. int rc;
  1038. smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
  1039. if (smb2_to_name == NULL) {
  1040. rc = -ENOMEM;
  1041. goto smb2_rename_path;
  1042. }
  1043. in_iov.iov_base = smb2_to_name;
  1044. in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
  1045. oparms = CIFS_OPARMS(cifs_sb, tcon, from_name, access, FILE_OPEN,
  1046. create_options, ACL_NO_MODE);
  1047. rc = smb2_compound_op(xid, tcon, cifs_sb, from_name,
  1048. &oparms, &in_iov, &command, 1,
  1049. cfile, NULL, NULL, dentry);
  1050. smb2_rename_path:
  1051. kfree(smb2_to_name);
  1052. return rc;
  1053. }
  1054. int smb2_rename_path(const unsigned int xid,
  1055. struct cifs_tcon *tcon,
  1056. struct dentry *source_dentry,
  1057. const char *from_name, const char *to_name,
  1058. struct cifs_sb_info *cifs_sb)
  1059. {
  1060. struct cifsFileInfo *cfile;
  1061. __u32 co = file_create_options(source_dentry);
  1062. drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
  1063. cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
  1064. int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
  1065. co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
  1066. if (rc == -EINVAL) {
  1067. cifs_dbg(FYI, "invalid lease key, resending request without lease");
  1068. cifs_get_writable_path(tcon, from_name,
  1069. FIND_WR_WITH_DELETE, &cfile);
  1070. rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
  1071. co, DELETE, SMB2_OP_RENAME, cfile, NULL);
  1072. }
  1073. return rc;
  1074. }
  1075. int smb2_create_hardlink(const unsigned int xid,
  1076. struct cifs_tcon *tcon,
  1077. struct dentry *source_dentry,
  1078. const char *from_name, const char *to_name,
  1079. struct cifs_sb_info *cifs_sb)
  1080. {
  1081. __u32 co = file_create_options(source_dentry);
  1082. return smb2_set_path_attr(xid, tcon, from_name, to_name,
  1083. cifs_sb, co, FILE_READ_ATTRIBUTES,
  1084. SMB2_OP_HARDLINK, NULL, NULL);
  1085. }
  1086. int
  1087. smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
  1088. const char *full_path, __u64 size,
  1089. struct cifs_sb_info *cifs_sb, bool set_alloc,
  1090. struct dentry *dentry)
  1091. {
  1092. struct cifs_open_parms oparms;
  1093. struct cifsFileInfo *cfile;
  1094. struct kvec in_iov;
  1095. __le64 eof = cpu_to_le64(size);
  1096. int rc;
  1097. in_iov.iov_base = &eof;
  1098. in_iov.iov_len = sizeof(eof);
  1099. cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
  1100. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
  1101. FILE_OPEN, 0, ACL_NO_MODE);
  1102. rc = smb2_compound_op(xid, tcon, cifs_sb,
  1103. full_path, &oparms, &in_iov,
  1104. &(int){SMB2_OP_SET_EOF}, 1,
  1105. cfile, NULL, NULL, dentry);
  1106. if (rc == -EINVAL) {
  1107. cifs_dbg(FYI, "invalid lease key, resending request without lease");
  1108. cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
  1109. rc = smb2_compound_op(xid, tcon, cifs_sb,
  1110. full_path, &oparms, &in_iov,
  1111. &(int){SMB2_OP_SET_EOF}, 1,
  1112. cfile, NULL, NULL, NULL);
  1113. }
  1114. return rc;
  1115. }
  1116. int
  1117. smb2_set_file_info(struct inode *inode, const char *full_path,
  1118. FILE_BASIC_INFO *buf, const unsigned int xid)
  1119. {
  1120. struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), };
  1121. struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  1122. struct cifsFileInfo *cfile = NULL;
  1123. struct cifs_open_parms oparms;
  1124. struct tcon_link *tlink;
  1125. struct cifs_tcon *tcon;
  1126. int rc = 0;
  1127. tlink = cifs_sb_tlink(cifs_sb);
  1128. if (IS_ERR(tlink))
  1129. return PTR_ERR(tlink);
  1130. tcon = tlink_tcon(tlink);
  1131. if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
  1132. (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {
  1133. if (buf->Attributes == 0)
  1134. goto out; /* would be a no op, no sense sending this */
  1135. cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
  1136. }
  1137. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
  1138. FILE_OPEN, 0, ACL_NO_MODE);
  1139. rc = smb2_compound_op(xid, tcon, cifs_sb,
  1140. full_path, &oparms, &in_iov,
  1141. &(int){SMB2_OP_SET_INFO}, 1,
  1142. cfile, NULL, NULL, NULL);
  1143. out:
  1144. cifs_put_tlink(tlink);
  1145. return rc;
  1146. }
  1147. struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
  1148. struct super_block *sb,
  1149. const unsigned int xid,
  1150. struct cifs_tcon *tcon,
  1151. const char *full_path,
  1152. bool directory,
  1153. struct kvec *reparse_iov,
  1154. struct kvec *xattr_iov)
  1155. {
  1156. struct cifs_open_parms oparms;
  1157. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  1158. struct cifsFileInfo *cfile;
  1159. struct inode *new = NULL;
  1160. int out_buftype[4] = {};
  1161. struct kvec out_iov[4] = {};
  1162. struct kvec in_iov[2];
  1163. int cmds[2];
  1164. int rc;
  1165. int i;
  1166. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
  1167. SYNCHRONIZE | DELETE |
  1168. FILE_READ_ATTRIBUTES |
  1169. FILE_WRITE_ATTRIBUTES,
  1170. FILE_CREATE,
  1171. (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
  1172. ACL_NO_MODE);
  1173. if (xattr_iov)
  1174. oparms.ea_cctx = xattr_iov;
  1175. cmds[0] = SMB2_OP_SET_REPARSE;
  1176. in_iov[0] = *reparse_iov;
  1177. in_iov[1].iov_base = data;
  1178. in_iov[1].iov_len = sizeof(*data);
  1179. if (tcon->posix_extensions) {
  1180. cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
  1181. cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
  1182. rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
  1183. in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
  1184. if (!rc) {
  1185. rc = smb311_posix_get_inode_info(&new, full_path,
  1186. data, sb, xid);
  1187. }
  1188. } else {
  1189. cmds[1] = SMB2_OP_QUERY_INFO;
  1190. cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
  1191. rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
  1192. in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
  1193. if (!rc) {
  1194. rc = cifs_get_inode_info(&new, full_path,
  1195. data, sb, xid, NULL);
  1196. }
  1197. }
  1198. /*
  1199. * If CREATE was successful but SMB2_OP_SET_REPARSE failed then
  1200. * remove the intermediate object created by CREATE. Otherwise
  1201. * empty object stay on the server when reparse call failed.
  1202. */
  1203. if (rc &&
  1204. out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER &&
  1205. ((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS &&
  1206. (out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER ||
  1207. ((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS))
  1208. smb2_unlink(xid, tcon, full_path, cifs_sb, NULL);
  1209. for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
  1210. free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
  1211. return rc ? ERR_PTR(rc) : new;
  1212. }
  1213. int smb2_query_reparse_point(const unsigned int xid,
  1214. struct cifs_tcon *tcon,
  1215. struct cifs_sb_info *cifs_sb,
  1216. const char *full_path,
  1217. u32 *tag, struct kvec *rsp,
  1218. int *rsp_buftype)
  1219. {
  1220. struct cifs_open_parms oparms;
  1221. struct cifs_open_info_data data = {};
  1222. struct cifsFileInfo *cfile;
  1223. struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
  1224. int rc;
  1225. cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
  1226. cifs_get_readable_path(tcon, full_path, &cfile);
  1227. oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
  1228. FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
  1229. FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
  1230. rc = smb2_compound_op(xid, tcon, cifs_sb,
  1231. full_path, &oparms, &in_iov,
  1232. &(int){SMB2_OP_GET_REPARSE}, 1,
  1233. cfile, NULL, NULL, NULL);
  1234. if (rc)
  1235. goto out;
  1236. *tag = data.reparse.tag;
  1237. *rsp = data.reparse.io.iov;
  1238. *rsp_buftype = data.reparse.io.buftype;
  1239. memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
  1240. data.reparse.io.buftype = CIFS_NO_BUFFER;
  1241. out:
  1242. cifs_free_open_info(&data);
  1243. return rc;
  1244. }