Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  *
0004  *   Copyright (C) International Business Machines  Corp., 2002,2008
0005  *   Author(s): Steve French (sfrench@us.ibm.com)
0006  *
0007  */
0008 #include <linux/fs.h>
0009 #include <linux/stat.h>
0010 #include <linux/slab.h>
0011 #include <linux/namei.h>
0012 #include "cifsfs.h"
0013 #include "cifspdu.h"
0014 #include "cifsglob.h"
0015 #include "cifsproto.h"
0016 #include "cifs_debug.h"
0017 #include "cifs_fs_sb.h"
0018 #include "cifs_unicode.h"
0019 #include "smb2proto.h"
0020 #include "cifs_ioctl.h"
0021 
0022 /*
0023  * M-F Symlink Functions - Begin
0024  */
0025 
0026 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
0027 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
0028 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
0029 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
0030 #define CIFS_MF_SYMLINK_FILE_SIZE \
0031     (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
0032 
0033 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
0034 #define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
0035 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
0036 
0037 static int
0038 symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
0039 {
0040     int rc;
0041     struct crypto_shash *md5 = NULL;
0042     struct sdesc *sdescmd5 = NULL;
0043 
0044     rc = cifs_alloc_hash("md5", &md5, &sdescmd5);
0045     if (rc)
0046         goto symlink_hash_err;
0047 
0048     rc = crypto_shash_init(&sdescmd5->shash);
0049     if (rc) {
0050         cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
0051         goto symlink_hash_err;
0052     }
0053     rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
0054     if (rc) {
0055         cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
0056         goto symlink_hash_err;
0057     }
0058     rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
0059     if (rc)
0060         cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
0061 
0062 symlink_hash_err:
0063     cifs_free_hash(&md5, &sdescmd5);
0064     return rc;
0065 }
0066 
0067 static int
0068 parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
0069          char **_link_str)
0070 {
0071     int rc;
0072     unsigned int link_len;
0073     const char *md5_str1;
0074     const char *link_str;
0075     u8 md5_hash[16];
0076     char md5_str2[34];
0077 
0078     if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
0079         return -EINVAL;
0080 
0081     md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
0082     link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
0083 
0084     rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
0085     if (rc != 1)
0086         return -EINVAL;
0087 
0088     if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
0089         return -EINVAL;
0090 
0091     rc = symlink_hash(link_len, link_str, md5_hash);
0092     if (rc) {
0093         cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
0094         return rc;
0095     }
0096 
0097     scnprintf(md5_str2, sizeof(md5_str2),
0098           CIFS_MF_SYMLINK_MD5_FORMAT,
0099           CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
0100 
0101     if (strncmp(md5_str1, md5_str2, 17) != 0)
0102         return -EINVAL;
0103 
0104     if (_link_str) {
0105         *_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
0106         if (!*_link_str)
0107             return -ENOMEM;
0108     }
0109 
0110     *_link_len = link_len;
0111     return 0;
0112 }
0113 
0114 static int
0115 format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
0116 {
0117     int rc;
0118     unsigned int link_len;
0119     unsigned int ofs;
0120     u8 md5_hash[16];
0121 
0122     if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
0123         return -EINVAL;
0124 
0125     link_len = strlen(link_str);
0126 
0127     if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
0128         return -ENAMETOOLONG;
0129 
0130     rc = symlink_hash(link_len, link_str, md5_hash);
0131     if (rc) {
0132         cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
0133         return rc;
0134     }
0135 
0136     scnprintf(buf, buf_len,
0137           CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
0138           link_len,
0139           CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
0140 
0141     ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
0142     memcpy(buf + ofs, link_str, link_len);
0143 
0144     ofs += link_len;
0145     if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
0146         buf[ofs] = '\n';
0147         ofs++;
0148     }
0149 
0150     while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
0151         buf[ofs] = ' ';
0152         ofs++;
0153     }
0154 
0155     return 0;
0156 }
0157 
0158 bool
0159 couldbe_mf_symlink(const struct cifs_fattr *fattr)
0160 {
0161     if (!S_ISREG(fattr->cf_mode))
0162         /* it's not a symlink */
0163         return false;
0164 
0165     if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
0166         /* it's not a symlink */
0167         return false;
0168 
0169     return true;
0170 }
0171 
0172 static int
0173 create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
0174           struct cifs_sb_info *cifs_sb, const char *fromName,
0175           const char *toName)
0176 {
0177     int rc;
0178     u8 *buf;
0179     unsigned int bytes_written = 0;
0180 
0181     buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
0182     if (!buf)
0183         return -ENOMEM;
0184 
0185     rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
0186     if (rc)
0187         goto out;
0188 
0189     if (tcon->ses->server->ops->create_mf_symlink)
0190         rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
0191                     cifs_sb, fromName, buf, &bytes_written);
0192     else
0193         rc = -EOPNOTSUPP;
0194 
0195     if (rc)
0196         goto out;
0197 
0198     if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
0199         rc = -EIO;
0200 out:
0201     kfree(buf);
0202     return rc;
0203 }
0204 
0205 static int
0206 query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
0207          struct cifs_sb_info *cifs_sb, const unsigned char *path,
0208          char **symlinkinfo)
0209 {
0210     int rc;
0211     u8 *buf = NULL;
0212     unsigned int link_len = 0;
0213     unsigned int bytes_read = 0;
0214 
0215     buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
0216     if (!buf)
0217         return -ENOMEM;
0218 
0219     if (tcon->ses->server->ops->query_mf_symlink)
0220         rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
0221                           cifs_sb, path, buf, &bytes_read);
0222     else
0223         rc = -ENOSYS;
0224 
0225     if (rc)
0226         goto out;
0227 
0228     if (bytes_read == 0) { /* not a symlink */
0229         rc = -EINVAL;
0230         goto out;
0231     }
0232 
0233     rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
0234 out:
0235     kfree(buf);
0236     return rc;
0237 }
0238 
0239 int
0240 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
0241          struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
0242          const unsigned char *path)
0243 {
0244     int rc;
0245     u8 *buf = NULL;
0246     unsigned int link_len = 0;
0247     unsigned int bytes_read = 0;
0248 
0249     if (!couldbe_mf_symlink(fattr))
0250         /* it's not a symlink */
0251         return 0;
0252 
0253     buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
0254     if (!buf)
0255         return -ENOMEM;
0256 
0257     if (tcon->ses->server->ops->query_mf_symlink)
0258         rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
0259                           cifs_sb, path, buf, &bytes_read);
0260     else
0261         rc = -ENOSYS;
0262 
0263     if (rc)
0264         goto out;
0265 
0266     if (bytes_read == 0) /* not a symlink */
0267         goto out;
0268 
0269     rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
0270     if (rc == -EINVAL) {
0271         /* it's not a symlink */
0272         rc = 0;
0273         goto out;
0274     }
0275 
0276     if (rc != 0)
0277         goto out;
0278 
0279     /* it is a symlink */
0280     fattr->cf_eof = link_len;
0281     fattr->cf_mode &= ~S_IFMT;
0282     fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
0283     fattr->cf_dtype = DT_LNK;
0284 out:
0285     kfree(buf);
0286     return rc;
0287 }
0288 
0289 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
0290 /*
0291  * SMB 1.0 Protocol specific functions
0292  */
0293 
0294 int
0295 cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
0296               struct cifs_sb_info *cifs_sb, const unsigned char *path,
0297               char *pbuf, unsigned int *pbytes_read)
0298 {
0299     int rc;
0300     int oplock = 0;
0301     struct cifs_fid fid;
0302     struct cifs_open_parms oparms;
0303     struct cifs_io_parms io_parms = {0};
0304     int buf_type = CIFS_NO_BUFFER;
0305     FILE_ALL_INFO file_info;
0306 
0307     oparms.tcon = tcon;
0308     oparms.cifs_sb = cifs_sb;
0309     oparms.desired_access = GENERIC_READ;
0310     oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
0311     oparms.disposition = FILE_OPEN;
0312     oparms.path = path;
0313     oparms.fid = &fid;
0314     oparms.reconnect = false;
0315 
0316     rc = CIFS_open(xid, &oparms, &oplock, &file_info);
0317     if (rc)
0318         return rc;
0319 
0320     if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
0321         rc = -ENOENT;
0322         /* it's not a symlink */
0323         goto out;
0324     }
0325 
0326     io_parms.netfid = fid.netfid;
0327     io_parms.pid = current->tgid;
0328     io_parms.tcon = tcon;
0329     io_parms.offset = 0;
0330     io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
0331 
0332     rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
0333 out:
0334     CIFSSMBClose(xid, tcon, fid.netfid);
0335     return rc;
0336 }
0337 
0338 int
0339 cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
0340                struct cifs_sb_info *cifs_sb, const unsigned char *path,
0341                char *pbuf, unsigned int *pbytes_written)
0342 {
0343     int rc;
0344     int oplock = 0;
0345     struct cifs_fid fid;
0346     struct cifs_open_parms oparms;
0347     struct cifs_io_parms io_parms = {0};
0348 
0349     oparms.tcon = tcon;
0350     oparms.cifs_sb = cifs_sb;
0351     oparms.desired_access = GENERIC_WRITE;
0352     oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
0353     oparms.disposition = FILE_CREATE;
0354     oparms.path = path;
0355     oparms.fid = &fid;
0356     oparms.reconnect = false;
0357 
0358     rc = CIFS_open(xid, &oparms, &oplock, NULL);
0359     if (rc)
0360         return rc;
0361 
0362     io_parms.netfid = fid.netfid;
0363     io_parms.pid = current->tgid;
0364     io_parms.tcon = tcon;
0365     io_parms.offset = 0;
0366     io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
0367 
0368     rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
0369     CIFSSMBClose(xid, tcon, fid.netfid);
0370     return rc;
0371 }
0372 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
0373 
0374 /*
0375  * SMB 2.1/SMB3 Protocol specific functions
0376  */
0377 int
0378 smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
0379               struct cifs_sb_info *cifs_sb, const unsigned char *path,
0380               char *pbuf, unsigned int *pbytes_read)
0381 {
0382     int rc;
0383     struct cifs_fid fid;
0384     struct cifs_open_parms oparms;
0385     struct cifs_io_parms io_parms = {0};
0386     int buf_type = CIFS_NO_BUFFER;
0387     __le16 *utf16_path;
0388     __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
0389     struct smb2_file_all_info *pfile_info = NULL;
0390 
0391     oparms.tcon = tcon;
0392     oparms.cifs_sb = cifs_sb;
0393     oparms.desired_access = GENERIC_READ;
0394     oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
0395     oparms.disposition = FILE_OPEN;
0396     oparms.fid = &fid;
0397     oparms.reconnect = false;
0398 
0399     utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
0400     if (utf16_path == NULL)
0401         return -ENOMEM;
0402 
0403     pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
0404                  GFP_KERNEL);
0405 
0406     if (pfile_info == NULL) {
0407         kfree(utf16_path);
0408         return  -ENOMEM;
0409     }
0410 
0411     rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
0412                NULL, NULL);
0413     if (rc)
0414         goto qmf_out_open_fail;
0415 
0416     if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
0417         /* it's not a symlink */
0418         rc = -ENOENT; /* Is there a better rc to return? */
0419         goto qmf_out;
0420     }
0421 
0422     io_parms.netfid = fid.netfid;
0423     io_parms.pid = current->tgid;
0424     io_parms.tcon = tcon;
0425     io_parms.offset = 0;
0426     io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
0427     io_parms.persistent_fid = fid.persistent_fid;
0428     io_parms.volatile_fid = fid.volatile_fid;
0429     rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
0430 qmf_out:
0431     SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
0432 qmf_out_open_fail:
0433     kfree(utf16_path);
0434     kfree(pfile_info);
0435     return rc;
0436 }
0437 
0438 int
0439 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
0440                struct cifs_sb_info *cifs_sb, const unsigned char *path,
0441                char *pbuf, unsigned int *pbytes_written)
0442 {
0443     int rc;
0444     struct cifs_fid fid;
0445     struct cifs_open_parms oparms;
0446     struct cifs_io_parms io_parms = {0};
0447     __le16 *utf16_path;
0448     __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
0449     struct kvec iov[2];
0450 
0451     cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
0452 
0453     utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
0454     if (!utf16_path)
0455         return -ENOMEM;
0456 
0457     oparms.tcon = tcon;
0458     oparms.cifs_sb = cifs_sb;
0459     oparms.desired_access = GENERIC_WRITE;
0460     oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
0461     oparms.disposition = FILE_CREATE;
0462     oparms.fid = &fid;
0463     oparms.reconnect = false;
0464 
0465     rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
0466                NULL, NULL);
0467     if (rc) {
0468         kfree(utf16_path);
0469         return rc;
0470     }
0471 
0472     io_parms.netfid = fid.netfid;
0473     io_parms.pid = current->tgid;
0474     io_parms.tcon = tcon;
0475     io_parms.offset = 0;
0476     io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
0477     io_parms.persistent_fid = fid.persistent_fid;
0478     io_parms.volatile_fid = fid.volatile_fid;
0479 
0480     /* iov[0] is reserved for smb header */
0481     iov[1].iov_base = pbuf;
0482     iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
0483 
0484     rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
0485 
0486     /* Make sure we wrote all of the symlink data */
0487     if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
0488         rc = -EIO;
0489 
0490     SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
0491 
0492     kfree(utf16_path);
0493     return rc;
0494 }
0495 
0496 /*
0497  * M-F Symlink Functions - End
0498  */
0499 
0500 int
0501 cifs_hardlink(struct dentry *old_file, struct inode *inode,
0502           struct dentry *direntry)
0503 {
0504     int rc = -EACCES;
0505     unsigned int xid;
0506     const char *from_name, *to_name;
0507     void *page1, *page2;
0508     struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
0509     struct tcon_link *tlink;
0510     struct cifs_tcon *tcon;
0511     struct TCP_Server_Info *server;
0512     struct cifsInodeInfo *cifsInode;
0513 
0514     if (unlikely(cifs_forced_shutdown(cifs_sb)))
0515         return -EIO;
0516 
0517     tlink = cifs_sb_tlink(cifs_sb);
0518     if (IS_ERR(tlink))
0519         return PTR_ERR(tlink);
0520     tcon = tlink_tcon(tlink);
0521 
0522     xid = get_xid();
0523     page1 = alloc_dentry_path();
0524     page2 = alloc_dentry_path();
0525 
0526     from_name = build_path_from_dentry(old_file, page1);
0527     if (IS_ERR(from_name)) {
0528         rc = PTR_ERR(from_name);
0529         goto cifs_hl_exit;
0530     }
0531     to_name = build_path_from_dentry(direntry, page2);
0532     if (IS_ERR(to_name)) {
0533         rc = PTR_ERR(to_name);
0534         goto cifs_hl_exit;
0535     }
0536 
0537 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
0538     if (tcon->unix_ext)
0539         rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
0540                         cifs_sb->local_nls,
0541                         cifs_remap(cifs_sb));
0542     else {
0543 #else
0544     {
0545 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
0546         server = tcon->ses->server;
0547         if (!server->ops->create_hardlink) {
0548             rc = -ENOSYS;
0549             goto cifs_hl_exit;
0550         }
0551         rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
0552                           cifs_sb);
0553         if ((rc == -EIO) || (rc == -EINVAL))
0554             rc = -EOPNOTSUPP;
0555     }
0556 
0557     d_drop(direntry);   /* force new lookup from server of target */
0558 
0559     /*
0560      * if source file is cached (oplocked) revalidate will not go to server
0561      * until the file is closed or oplock broken so update nlinks locally
0562      */
0563     if (d_really_is_positive(old_file)) {
0564         cifsInode = CIFS_I(d_inode(old_file));
0565         if (rc == 0) {
0566             spin_lock(&d_inode(old_file)->i_lock);
0567             inc_nlink(d_inode(old_file));
0568             spin_unlock(&d_inode(old_file)->i_lock);
0569 
0570             /*
0571              * parent dir timestamps will update from srv within a
0572              * second, would it really be worth it to set the parent
0573              * dir cifs inode time to zero to force revalidate
0574              * (faster) for it too?
0575              */
0576         }
0577         /*
0578          * if not oplocked will force revalidate to get info on source
0579          * file from srv.  Note Samba server prior to 4.2 has bug -
0580          * not updating src file ctime on hardlinks but Windows servers
0581          * handle it properly
0582          */
0583         cifsInode->time = 0;
0584 
0585         /*
0586          * Will update parent dir timestamps from srv within a second.
0587          * Would it really be worth it to set the parent dir (cifs
0588          * inode) time field to zero to force revalidate on parent
0589          * directory faster ie
0590          *
0591          * CIFS_I(inode)->time = 0;
0592          */
0593     }
0594 
0595 cifs_hl_exit:
0596     free_dentry_path(page1);
0597     free_dentry_path(page2);
0598     free_xid(xid);
0599     cifs_put_tlink(tlink);
0600     return rc;
0601 }
0602 
0603 const char *
0604 cifs_get_link(struct dentry *direntry, struct inode *inode,
0605           struct delayed_call *done)
0606 {
0607     int rc = -ENOMEM;
0608     unsigned int xid;
0609     const char *full_path;
0610     void *page;
0611     char *target_path = NULL;
0612     struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
0613     struct tcon_link *tlink = NULL;
0614     struct cifs_tcon *tcon;
0615     struct TCP_Server_Info *server;
0616 
0617     if (!direntry)
0618         return ERR_PTR(-ECHILD);
0619 
0620     xid = get_xid();
0621 
0622     tlink = cifs_sb_tlink(cifs_sb);
0623     if (IS_ERR(tlink)) {
0624         free_xid(xid);
0625         return ERR_CAST(tlink);
0626     }
0627     tcon = tlink_tcon(tlink);
0628     server = tcon->ses->server;
0629 
0630     page = alloc_dentry_path();
0631     full_path = build_path_from_dentry(direntry, page);
0632     if (IS_ERR(full_path)) {
0633         free_xid(xid);
0634         cifs_put_tlink(tlink);
0635         free_dentry_path(page);
0636         return ERR_CAST(full_path);
0637     }
0638 
0639     cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
0640 
0641     rc = -EACCES;
0642     /*
0643      * First try Minshall+French Symlinks, if configured
0644      * and fallback to UNIX Extensions Symlinks.
0645      */
0646     if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
0647         rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
0648                       &target_path);
0649 
0650     if (rc != 0 && server->ops->query_symlink) {
0651         struct cifsInodeInfo *cifsi = CIFS_I(inode);
0652         bool reparse_point = false;
0653 
0654         if (cifsi->cifsAttrs & ATTR_REPARSE)
0655             reparse_point = true;
0656 
0657         rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
0658                         &target_path, reparse_point);
0659     }
0660 
0661     free_dentry_path(page);
0662     free_xid(xid);
0663     cifs_put_tlink(tlink);
0664     if (rc != 0) {
0665         kfree(target_path);
0666         return ERR_PTR(rc);
0667     }
0668     set_delayed_call(done, kfree_link, target_path);
0669     return target_path;
0670 }
0671 
0672 int
0673 cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
0674          struct dentry *direntry, const char *symname)
0675 {
0676     int rc = -EOPNOTSUPP;
0677     unsigned int xid;
0678     struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
0679     struct tcon_link *tlink;
0680     struct cifs_tcon *pTcon;
0681     const char *full_path;
0682     void *page;
0683     struct inode *newinode = NULL;
0684 
0685     if (unlikely(cifs_forced_shutdown(cifs_sb)))
0686         return -EIO;
0687 
0688     page = alloc_dentry_path();
0689     if (!page)
0690         return -ENOMEM;
0691 
0692     xid = get_xid();
0693 
0694     tlink = cifs_sb_tlink(cifs_sb);
0695     if (IS_ERR(tlink)) {
0696         rc = PTR_ERR(tlink);
0697         goto symlink_exit;
0698     }
0699     pTcon = tlink_tcon(tlink);
0700 
0701     full_path = build_path_from_dentry(direntry, page);
0702     if (IS_ERR(full_path)) {
0703         rc = PTR_ERR(full_path);
0704         goto symlink_exit;
0705     }
0706 
0707     cifs_dbg(FYI, "Full path: %s\n", full_path);
0708     cifs_dbg(FYI, "symname is %s\n", symname);
0709 
0710     /* BB what if DFS and this volume is on different share? BB */
0711     if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
0712         rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
0713 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
0714     else if (pTcon->unix_ext)
0715         rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
0716                        cifs_sb->local_nls,
0717                        cifs_remap(cifs_sb));
0718 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
0719     /* else
0720        rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
0721                     cifs_sb_target->local_nls); */
0722 
0723     if (rc == 0) {
0724         if (pTcon->posix_extensions)
0725             rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid);
0726         else if (pTcon->unix_ext)
0727             rc = cifs_get_inode_info_unix(&newinode, full_path,
0728                               inode->i_sb, xid);
0729         else
0730             rc = cifs_get_inode_info(&newinode, full_path, NULL,
0731                          inode->i_sb, xid, NULL);
0732 
0733         if (rc != 0) {
0734             cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
0735                  rc);
0736         } else {
0737             d_instantiate(direntry, newinode);
0738         }
0739     }
0740 symlink_exit:
0741     free_dentry_path(page);
0742     cifs_put_tlink(tlink);
0743     free_xid(xid);
0744     return rc;
0745 }