Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
link.c
Go to the documentation of this file.
1 /*
2  * fs/cifs/link.c
3  *
4  * Copyright (C) International Business Machines Corp., 2002,2008
5  * Author(s): Steve French ([email protected])
6  *
7  * This library is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published
9  * by the Free Software Foundation; either version 2.1 of the License, or
10  * (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15  * the GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 #include <linux/fs.h>
22 #include <linux/stat.h>
23 #include <linux/slab.h>
24 #include <linux/namei.h>
25 #include "cifsfs.h"
26 #include "cifspdu.h"
27 #include "cifsglob.h"
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
30 #include "cifs_fs_sb.h"
31 
32 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
33 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
34 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
35 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
36 #define CIFS_MF_SYMLINK_FILE_SIZE \
37  (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
38 
39 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
40 #define CIFS_MF_SYMLINK_MD5_FORMAT \
41  "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
42 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
43  md5_hash[0], md5_hash[1], md5_hash[2], md5_hash[3], \
44  md5_hash[4], md5_hash[5], md5_hash[6], md5_hash[7], \
45  md5_hash[8], md5_hash[9], md5_hash[10], md5_hash[11],\
46  md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
47 
48 static int
49 symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
50 {
51  int rc;
52  unsigned int size;
53  struct crypto_shash *md5;
54  struct sdesc *sdescmd5;
55 
56  md5 = crypto_alloc_shash("md5", 0, 0);
57  if (IS_ERR(md5)) {
58  rc = PTR_ERR(md5);
59  cERROR(1, "%s: Crypto md5 allocation error %d", __func__, rc);
60  return rc;
61  }
62  size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
63  sdescmd5 = kmalloc(size, GFP_KERNEL);
64  if (!sdescmd5) {
65  rc = -ENOMEM;
66  cERROR(1, "%s: Memory allocation failure", __func__);
67  goto symlink_hash_err;
68  }
69  sdescmd5->shash.tfm = md5;
70  sdescmd5->shash.flags = 0x0;
71 
72  rc = crypto_shash_init(&sdescmd5->shash);
73  if (rc) {
74  cERROR(1, "%s: Could not init md5 shash", __func__);
75  goto symlink_hash_err;
76  }
77  rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
78  if (rc) {
79  cERROR(1, "%s: Could not update iwth link_str", __func__);
80  goto symlink_hash_err;
81  }
82  rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
83  if (rc)
84  cERROR(1, "%s: Could not generate md5 hash", __func__);
85 
86 symlink_hash_err:
87  crypto_free_shash(md5);
88  kfree(sdescmd5);
89 
90  return rc;
91 }
92 
93 static int
94 CIFSParseMFSymlink(const u8 *buf,
95  unsigned int buf_len,
96  unsigned int *_link_len,
97  char **_link_str)
98 {
99  int rc;
100  unsigned int link_len;
101  const char *md5_str1;
102  const char *link_str;
103  u8 md5_hash[16];
104  char md5_str2[34];
105 
106  if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
107  return -EINVAL;
108 
109  md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
110  link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
111 
112  rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
113  if (rc != 1)
114  return -EINVAL;
115 
116  rc = symlink_hash(link_len, link_str, md5_hash);
117  if (rc) {
118  cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
119  return rc;
120  }
121 
122  snprintf(md5_str2, sizeof(md5_str2),
124  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
125 
126  if (strncmp(md5_str1, md5_str2, 17) != 0)
127  return -EINVAL;
128 
129  if (_link_str) {
130  *_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
131  if (!*_link_str)
132  return -ENOMEM;
133  }
134 
135  *_link_len = link_len;
136  return 0;
137 }
138 
139 static int
140 CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
141 {
142  int rc;
143  unsigned int link_len;
144  unsigned int ofs;
145  u8 md5_hash[16];
146 
147  if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
148  return -EINVAL;
149 
150  link_len = strlen(link_str);
151 
152  if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
153  return -ENAMETOOLONG;
154 
155  rc = symlink_hash(link_len, link_str, md5_hash);
156  if (rc) {
157  cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
158  return rc;
159  }
160 
161  snprintf(buf, buf_len,
163  link_len,
164  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
165 
167  memcpy(buf + ofs, link_str, link_len);
168 
169  ofs += link_len;
170  if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
171  buf[ofs] = '\n';
172  ofs++;
173  }
174 
175  while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
176  buf[ofs] = ' ';
177  ofs++;
178  }
179 
180  return 0;
181 }
182 
183 static int
184 CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
185  const char *fromName, const char *toName,
186  struct cifs_sb_info *cifs_sb)
187 {
188  int rc;
189  int oplock = 0;
190  int remap;
191  int create_options = CREATE_NOT_DIR;
192  __u16 netfid = 0;
193  u8 *buf;
194  unsigned int bytes_written = 0;
195  struct cifs_io_parms io_parms;
196  struct nls_table *nls_codepage;
197 
198  nls_codepage = cifs_sb->local_nls;
199  remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
200 
202  if (!buf)
203  return -ENOMEM;
204 
205  rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
206  if (rc != 0) {
207  kfree(buf);
208  return rc;
209  }
210 
211  if (backup_cred(cifs_sb))
212  create_options |= CREATE_OPEN_BACKUP_INTENT;
213 
214  rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
215  create_options, &netfid, &oplock, NULL,
216  nls_codepage, remap);
217  if (rc != 0) {
218  kfree(buf);
219  return rc;
220  }
221 
222  io_parms.netfid = netfid;
223  io_parms.pid = current->tgid;
224  io_parms.tcon = tcon;
225  io_parms.offset = 0;
226  io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
227 
228  rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
229  CIFSSMBClose(xid, tcon, netfid);
230  kfree(buf);
231  if (rc != 0)
232  return rc;
233 
234  if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
235  return -EIO;
236 
237  return 0;
238 }
239 
240 static int
241 CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
242  const unsigned char *searchName, char **symlinkinfo,
243  const struct nls_table *nls_codepage, int remap)
244 {
245  int rc;
246  int oplock = 0;
247  __u16 netfid = 0;
248  u8 *buf;
249  char *pbuf;
250  unsigned int bytes_read = 0;
251  int buf_type = CIFS_NO_BUFFER;
252  unsigned int link_len = 0;
253  struct cifs_io_parms io_parms;
254  FILE_ALL_INFO file_info;
255 
256  rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
257  CREATE_NOT_DIR, &netfid, &oplock, &file_info,
258  nls_codepage, remap);
259  if (rc != 0)
260  return rc;
261 
262  if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
263  CIFSSMBClose(xid, tcon, netfid);
264  /* it's not a symlink */
265  return -EINVAL;
266  }
267 
269  if (!buf)
270  return -ENOMEM;
271  pbuf = buf;
272  io_parms.netfid = netfid;
273  io_parms.pid = current->tgid;
274  io_parms.tcon = tcon;
275  io_parms.offset = 0;
276  io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
277 
278  rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
279  CIFSSMBClose(xid, tcon, netfid);
280  if (rc != 0) {
281  kfree(buf);
282  return rc;
283  }
284 
285  rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
286  kfree(buf);
287  if (rc != 0)
288  return rc;
289 
290  return 0;
291 }
292 
293 bool
294 CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
295 {
296  if (!(fattr->cf_mode & S_IFREG))
297  /* it's not a symlink */
298  return false;
299 
300  if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
301  /* it's not a symlink */
302  return false;
303 
304  return true;
305 }
306 
307 int
309  const unsigned char *path,
310  struct cifs_sb_info *cifs_sb, unsigned int xid)
311 {
312  int rc;
313  int oplock = 0;
314  __u16 netfid = 0;
315  struct tcon_link *tlink;
316  struct cifs_tcon *pTcon;
317  struct cifs_io_parms io_parms;
318  u8 *buf;
319  char *pbuf;
320  unsigned int bytes_read = 0;
321  int buf_type = CIFS_NO_BUFFER;
322  unsigned int link_len = 0;
323  FILE_ALL_INFO file_info;
324 
325  if (!CIFSCouldBeMFSymlink(fattr))
326  /* it's not a symlink */
327  return 0;
328 
329  tlink = cifs_sb_tlink(cifs_sb);
330  if (IS_ERR(tlink))
331  return PTR_ERR(tlink);
332  pTcon = tlink_tcon(tlink);
333 
334  rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
335  CREATE_NOT_DIR, &netfid, &oplock, &file_info,
336  cifs_sb->local_nls,
337  cifs_sb->mnt_cifs_flags &
339  if (rc != 0)
340  goto out;
341 
342  if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
343  CIFSSMBClose(xid, pTcon, netfid);
344  /* it's not a symlink */
345  goto out;
346  }
347 
349  if (!buf) {
350  rc = -ENOMEM;
351  goto out;
352  }
353  pbuf = buf;
354  io_parms.netfid = netfid;
355  io_parms.pid = current->tgid;
356  io_parms.tcon = pTcon;
357  io_parms.offset = 0;
359 
360  rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
361  CIFSSMBClose(xid, pTcon, netfid);
362  if (rc != 0) {
363  kfree(buf);
364  goto out;
365  }
366 
367  rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
368  kfree(buf);
369  if (rc == -EINVAL) {
370  /* it's not a symlink */
371  rc = 0;
372  goto out;
373  }
374 
375  if (rc != 0)
376  goto out;
377 
378  /* it is a symlink */
379  fattr->cf_eof = link_len;
380  fattr->cf_mode &= ~S_IFMT;
381  fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
382  fattr->cf_dtype = DT_LNK;
383 out:
384  cifs_put_tlink(tlink);
385  return rc;
386 }
387 
388 int
389 cifs_hardlink(struct dentry *old_file, struct inode *inode,
390  struct dentry *direntry)
391 {
392  int rc = -EACCES;
393  unsigned int xid;
394  char *from_name = NULL;
395  char *to_name = NULL;
396  struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
397  struct tcon_link *tlink;
398  struct cifs_tcon *tcon;
399  struct TCP_Server_Info *server;
400  struct cifsInodeInfo *cifsInode;
401 
402  tlink = cifs_sb_tlink(cifs_sb);
403  if (IS_ERR(tlink))
404  return PTR_ERR(tlink);
405  tcon = tlink_tcon(tlink);
406 
407  xid = get_xid();
408 
409  from_name = build_path_from_dentry(old_file);
410  to_name = build_path_from_dentry(direntry);
411  if ((from_name == NULL) || (to_name == NULL)) {
412  rc = -ENOMEM;
413  goto cifs_hl_exit;
414  }
415 
416  if (tcon->unix_ext)
417  rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
418  cifs_sb->local_nls,
419  cifs_sb->mnt_cifs_flags &
421  else {
422  server = tcon->ses->server;
423  if (!server->ops->create_hardlink)
424  return -ENOSYS;
425  rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
426  cifs_sb);
427  if ((rc == -EIO) || (rc == -EINVAL))
428  rc = -EOPNOTSUPP;
429  }
430 
431  d_drop(direntry); /* force new lookup from server of target */
432 
433  /*
434  * if source file is cached (oplocked) revalidate will not go to server
435  * until the file is closed or oplock broken so update nlinks locally
436  */
437  if (old_file->d_inode) {
438  cifsInode = CIFS_I(old_file->d_inode);
439  if (rc == 0) {
440  spin_lock(&old_file->d_inode->i_lock);
441  inc_nlink(old_file->d_inode);
442  spin_unlock(&old_file->d_inode->i_lock);
443  /*
444  * BB should we make this contingent on superblock flag
445  * NOATIME?
446  */
447  /* old_file->d_inode->i_ctime = CURRENT_TIME; */
448  /*
449  * parent dir timestamps will update from srv within a
450  * second, would it really be worth it to set the parent
451  * dir cifs inode time to zero to force revalidate
452  * (faster) for it too?
453  */
454  }
455  /*
456  * if not oplocked will force revalidate to get info on source
457  * file from srv
458  */
459  cifsInode->time = 0;
460 
461  /*
462  * Will update parent dir timestamps from srv within a second.
463  * Would it really be worth it to set the parent dir (cifs
464  * inode) time field to zero to force revalidate on parent
465  * directory faster ie
466  *
467  * CIFS_I(inode)->time = 0;
468  */
469  }
470 
471 cifs_hl_exit:
472  kfree(from_name);
473  kfree(to_name);
474  free_xid(xid);
475  cifs_put_tlink(tlink);
476  return rc;
477 }
478 
479 void *
480 cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
481 {
482  struct inode *inode = direntry->d_inode;
483  int rc = -ENOMEM;
484  unsigned int xid;
485  char *full_path = NULL;
486  char *target_path = NULL;
487  struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
488  struct tcon_link *tlink = NULL;
489  struct cifs_tcon *tcon;
490 
491  xid = get_xid();
492 
493  tlink = cifs_sb_tlink(cifs_sb);
494  if (IS_ERR(tlink)) {
495  rc = PTR_ERR(tlink);
496  tlink = NULL;
497  goto out;
498  }
499  tcon = tlink_tcon(tlink);
500 
501  /*
502  * For now, we just handle symlinks with unix extensions enabled.
503  * Eventually we should handle NTFS reparse points, and MacOS
504  * symlink support. For instance...
505  *
506  * rc = CIFSSMBQueryReparseLinkInfo(...)
507  *
508  * For now, just return -EACCES when the server doesn't support posix
509  * extensions. Note that we still allow querying symlinks when posix
510  * extensions are manually disabled. We could disable these as well
511  * but there doesn't seem to be any harm in allowing the client to
512  * read them.
513  */
514  if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
515  !cap_unix(tcon->ses)) {
516  rc = -EACCES;
517  goto out;
518  }
519 
520  full_path = build_path_from_dentry(direntry);
521  if (!full_path)
522  goto out;
523 
524  cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);
525 
526  rc = -EACCES;
527  /*
528  * First try Minshall+French Symlinks, if configured
529  * and fallback to UNIX Extensions Symlinks.
530  */
531  if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
532  rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
533  cifs_sb->local_nls,
534  cifs_sb->mnt_cifs_flags &
536 
537  if ((rc != 0) && cap_unix(tcon->ses))
538  rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
539  cifs_sb->local_nls);
540 
541  kfree(full_path);
542 out:
543  if (rc != 0) {
544  kfree(target_path);
545  target_path = ERR_PTR(rc);
546  }
547 
548  free_xid(xid);
549  if (tlink)
550  cifs_put_tlink(tlink);
551  nd_set_link(nd, target_path);
552  return NULL;
553 }
554 
555 int
556 cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
557 {
558  int rc = -EOPNOTSUPP;
559  unsigned int xid;
560  struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
561  struct tcon_link *tlink;
562  struct cifs_tcon *pTcon;
563  char *full_path = NULL;
564  struct inode *newinode = NULL;
565 
566  xid = get_xid();
567 
568  tlink = cifs_sb_tlink(cifs_sb);
569  if (IS_ERR(tlink)) {
570  rc = PTR_ERR(tlink);
571  goto symlink_exit;
572  }
573  pTcon = tlink_tcon(tlink);
574 
575  full_path = build_path_from_dentry(direntry);
576  if (full_path == NULL) {
577  rc = -ENOMEM;
578  goto symlink_exit;
579  }
580 
581  cFYI(1, "Full path: %s", full_path);
582  cFYI(1, "symname is %s", symname);
583 
584  /* BB what if DFS and this volume is on different share? BB */
585  if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
586  rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
587  cifs_sb);
588  else if (pTcon->unix_ext)
589  rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
590  cifs_sb->local_nls);
591  /* else
592  rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
593  cifs_sb_target->local_nls); */
594 
595  if (rc == 0) {
596  if (pTcon->unix_ext)
597  rc = cifs_get_inode_info_unix(&newinode, full_path,
598  inode->i_sb, xid);
599  else
600  rc = cifs_get_inode_info(&newinode, full_path, NULL,
601  inode->i_sb, xid, NULL);
602 
603  if (rc != 0) {
604  cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d",
605  rc);
606  } else {
607  d_instantiate(direntry, newinode);
608  }
609  }
610 symlink_exit:
611  kfree(full_path);
612  cifs_put_tlink(tlink);
613  free_xid(xid);
614  return rc;
615 }
616 
617 void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
618 {
619  char *p = nd_get_link(nd);
620  if (!IS_ERR(p))
621  kfree(p);
622 }