patch-2.3.31 linux/fs/ncpfs/symlink.c

Next file: linux/fs/nfs/inode.c
Previous file: linux/fs/ncpfs/ncplib_kernel.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.30/linux/fs/ncpfs/symlink.c linux/fs/ncpfs/symlink.c
@@ -74,8 +74,8 @@
 				      unsigned int follow)
 {
 	struct inode *inode=dentry->d_inode;
-	int error, length, cnt;
-	char *link;
+	int error, length, len, cnt;
+	char *link, *buf;
 
 #ifdef DEBUG
 	PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
@@ -91,7 +91,7 @@
 		return ERR_PTR(-EIO);
 	}
 
-	for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
+	for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
 		if (cnt > 10) {
 			dput(base);
 			return ERR_PTR(-EAGAIN); /* -ENOMEM? */
@@ -108,14 +108,25 @@
 		kfree(link);
 		return ERR_PTR(-EIO);
 	}
- 
-	link[length]=0;
 
-	vol2io(NCP_SERVER(inode), link+8, 0);
+	len = NCP_MAX_SYMLINK_SIZE;
+	buf = (char *) kmalloc(len, GFP_NFS);
+	if (!buf) {
+		dput(base);
+		kfree(link);
+		return ERR_PTR(-EAGAIN);
+	}
+	error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
+	kfree(link);
+	if (error) {
+		dput(base);
+		kfree(buf);
+		return ERR_PTR(error);
+	}
 	
 	/* UPDATE_ATIME(inode); */
-	base=lookup_dentry(link+8, base, follow);
-	kfree(link);
+	base = lookup_dentry(buf, base, follow);
+	kfree(buf);
 
 	return base;
 }
@@ -125,8 +136,8 @@
 static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
 {
 	struct inode *inode=dentry->d_inode;
-	char *link;
-	int length,error;
+	char *link, *buf;
+	int length, len, error;
 
 #ifdef DEBUG
 	PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
@@ -138,7 +149,7 @@
 	if(ncp_make_open(inode,O_RDONLY))
 		return -EIO;
 
-	if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL)
+	if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE,GFP_NFS))==NULL)
 		return -ENOMEM;
 
 	error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
@@ -150,15 +161,25 @@
 		goto out;
 	}
 
-	link[length] = 0;
+	len = NCP_MAX_SYMLINK_SIZE;
+	buf = (char *) kmalloc(len, GFP_NFS);
+	if (!buf) {
+		error = -ENOMEM;
+		goto out;
+	}
+	error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
+	if (error || buflen < len) {
+		error = -EIO;
+		kfree(buf);
+		goto out;
+	}
 
-	vol2io(NCP_SERVER(inode), link+8, 0);
-	
-	error = length - 8;
-	if(copy_to_user(buffer, link+8, error))
+	error = len;
+	if(copy_to_user(buffer, buf, error))
 		error = -EFAULT;
-      
-out:;
+	kfree(buf);
+
+out:
 	kfree(link);
 	return error;
 }
@@ -166,9 +187,9 @@
 /* ----- create a new symbolic link -------------------------------------- */
  
 int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
-	int i,length;
 	struct inode *inode;
 	char *link;
+	int length, err, i;
 
 #ifdef DEBUG
 	PRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
@@ -177,7 +198,7 @@
 	if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
 		return -EPERM;	/* EPERM is returned by VFS if symlink procedure does not exist */
 
-	if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE)
+	if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE-8)
 		return -EINVAL;
 
 	if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
@@ -192,12 +213,16 @@
 
 	((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
 	((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
-	memcpy(link+8, symname, length+1); /* including last zero for io2vol */
 
 	/* map to/from server charset, do not touch upper/lower case as
 	   symlink can point out of ncp filesystem */
-	io2vol(NCP_SERVER(inode), link+8, 0);
-	
+	length += 1;
+	err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0);
+	if (err) {
+		kfree(link);
+		return err;
+	}
+
 	if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 
 	    		    0, length+8, link, &i) || i!=length+8) {
 		kfree(link);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)