patch-2.4.18 linux/fs/smbfs/proc.c
Next file: linux/fs/super.c
Previous file: linux/fs/smbfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 343
- Date:
Thu Feb 21 18:10:13 2002
- Orig file:
linux.orig/fs/smbfs/proc.c
- Orig date:
Sun Oct 7 23:47:43 2001
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/fs/smbfs/proc.c linux/fs/smbfs/proc.c
@@ -103,6 +103,8 @@
struct nls_table *nls_from,
struct nls_table *nls_to)
{
+ if (olen < ilen)
+ return -ENAMETOOLONG;
memcpy(output, input, ilen);
return ilen;
}
@@ -126,20 +128,21 @@
/* convert by changing to unicode and back to the new cp */
n = nls_from->char2uni((unsigned char *)input, ilen, &ch);
if (n < 0)
- goto out;
+ goto fail;
input += n;
ilen -= n;
n = nls_to->uni2char(ch, output, olen);
if (n < 0)
- goto out;
+ goto fail;
output += n;
olen -= n;
len += n;
}
-out:
return len;
+fail:
+ return n;
}
static int setcodepage(struct nls_table **p, char *name)
@@ -214,71 +217,79 @@
* smb_build_path: build the path to entry and name storing it in buf.
* The path returned will have the trailing '\0'.
*/
-static int smb_build_path(struct smb_sb_info *server, char * buf,
+static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen,
struct dentry * entry, struct qstr * name)
{
char *path = buf;
int len;
+ if (maxlen < 2)
+ return -ENAMETOOLONG;
+
+ if (maxlen > SMB_MAXNAMELEN + 1)
+ maxlen = SMB_MAXNAMELEN + 1;
+
if (entry == NULL)
goto test_name_and_out;
/*
* If IS_ROOT, we have to do no walking at all.
*/
- if (IS_ROOT(entry)) {
- *(path++) = '\\';
- if (name != NULL)
- goto name_and_out;
- goto out;
+ if (IS_ROOT(entry) && !name) {
+ *path++ = '\\';
+ *path++ = '\0';
+ return 2;
}
/*
* Build the path string walking the tree backward from end to ROOT
* and store it in reversed order [see reverse_string()]
*/
- for (;;) {
- if (entry->d_name.len > SMB_MAXNAMELEN)
- return -ENAMETOOLONG;
- if (path - buf + entry->d_name.len > SMB_MAXPATHLEN)
+ while (!IS_ROOT(entry)) {
+ if (maxlen < 3)
return -ENAMETOOLONG;
- len = server->convert(path, SMB_MAXNAMELEN,
+ len = server->convert(path, maxlen-2,
entry->d_name.name, entry->d_name.len,
server->local_nls, server->remote_nls);
+ if (len < 0)
+ return len;
reverse_string(path, len);
path += len;
-
- *(path++) = '\\';
+ *path++ = '\\';
+ maxlen -= len+1;
entry = entry->d_parent;
-
if (IS_ROOT(entry))
break;
}
-
reverse_string(buf, path-buf);
+ /* maxlen is at least 1 */
test_name_and_out:
- if (name != NULL) {
- *(path++) = '\\';
-name_and_out:
- len = server->convert(path, SMB_MAXNAMELEN,
+ if (name) {
+ if (maxlen < 3)
+ return -ENAMETOOLONG;
+ *path++ = '\\';
+ len = server->convert(path, maxlen-2,
name->name, name->len,
server->local_nls, server->remote_nls);
+ if (len < 0)
+ return len;
path += len;
+ maxlen -= len+1;
}
-out:
- *(path++) = '\0';
- return (path-buf);
+ /* maxlen is at least 1 */
+ *path++ = '\0';
+ return path-buf;
}
-static int smb_encode_path(struct smb_sb_info *server, char *buf,
+static int smb_encode_path(struct smb_sb_info *server, char *buf, int maxlen,
struct dentry *dir, struct qstr *name)
{
int result;
- result = smb_build_path(server, buf, dir, name);
+ result = smb_build_path(server, buf, maxlen, dir, name);
if (result < 0)
goto out;
if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
@@ -287,6 +298,23 @@
return result;
}
+static int smb_simple_encode_path(struct smb_sb_info *server, char **p,
+ struct dentry * entry, struct qstr * name)
+{
+ char *s = *p;
+ int res;
+ int maxlen = ((char *)server->packet + server->packet_size) - s;
+
+ if (!maxlen)
+ return -ENAMETOOLONG;
+ *s++ = 4;
+ res = smb_encode_path(server, s, maxlen-1, entry, name);
+ if (res < 0)
+ return res;
+ *p = s + res;
+ return 0;
+}
+
/* The following are taken directly from msdos-fs */
/* Linear day numbers of the respective 1sts in non-leap years. */
@@ -965,12 +993,9 @@
p = smb_setup_header(server, SMBopen, 2, 0);
WSET(server->packet, smb_vwv0, mode);
WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
- *p++ = 4;
- res = smb_encode_path(server, p, dentry, NULL);
+ res = smb_simple_encode_path(server, &p, dentry, NULL);
if (res < 0)
goto out;
- p += res;
-
smb_setup_bcc(server, p);
res = smb_request_ok(server, SMBopen, 7, 0);
@@ -1242,11 +1267,9 @@
p = smb_setup_header(server, SMBcreate, 3, 0);
WSET(server->packet, smb_vwv0, attr);
DSET(server->packet, smb_vwv1, utc2local(server, ctime));
- *p++ = 4;
- result = smb_encode_path(server, p, dentry, NULL);
+ result = smb_simple_encode_path(server, &p, dentry, NULL);
if (result < 0)
goto out;
- p += result;
smb_setup_bcc(server, p);
result = smb_request_ok(server, SMBcreate, 1, 0);
@@ -1275,19 +1298,12 @@
retry:
p = smb_setup_header(server, SMBmv, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
-
- *p++ = 4;
- result = smb_encode_path(server, p, old_dentry, NULL);
+ result = smb_simple_encode_path(server, &p, old_dentry, NULL);
if (result < 0)
goto out;
- p += result;
-
- *p++ = 4;
- result = smb_encode_path(server, p, new_dentry, NULL);
+ result = smb_simple_encode_path(server, &p, new_dentry, NULL);
if (result < 0)
goto out;
- p += result;
-
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
@@ -1315,11 +1331,9 @@
retry:
p = smb_setup_header(server, command, 0, 0);
- *p++ = 4;
- result = smb_encode_path(server, p, dentry, NULL);
+ result = smb_simple_encode_path(server, &p, dentry, NULL);
if (result < 0)
goto out;
- p += result;
smb_setup_bcc(server, p);
result = smb_request_ok(server, command, 0, 0);
@@ -1385,11 +1399,9 @@
retry:
p = smb_setup_header(server, SMBunlink, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
- *p++ = 4;
- result = smb_encode_path(server, p, dentry, NULL);
+ result = smb_simple_encode_path(server, &p, dentry, NULL);
if (result < 0)
goto out;
- p += result;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
@@ -1589,8 +1601,7 @@
struct smb_sb_info *server = server_from_dentry(dir);
struct qstr qname;
struct smb_fattr fattr;
-
- unsigned char *p;
+ char *p;
int result;
int i, first, entries_seen, entries;
int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE;
@@ -1612,17 +1623,26 @@
p = smb_setup_header(server, SMBsearch, 2, 0);
WSET(server->packet, smb_vwv0, entries_asked);
WSET(server->packet, smb_vwv1, aDIR);
- *p++ = 4;
if (first == 1) {
- result = smb_encode_path(server, p, dir, &mask);
+ result = smb_simple_encode_path(server, &p, dir, &mask);
if (result < 0)
goto unlock_return;
- p += result;
+ if (p + 3 > (char*)server->packet+server->packet_size) {
+ result = -ENAMETOOLONG;
+ goto unlock_return;
+ }
*p++ = 5;
WSET(p, 0, 0);
p += 2;
first = 0;
} else {
+ if (p + 5 + SMB_STATUS_SIZE >
+ (char*)server->packet + server->packet_size) {
+ result = -ENAMETOOLONG;
+ goto unlock_return;
+ }
+
+ *p++ = 4;
*p++ = 0;
*p++ = 5;
WSET(p, 0, SMB_STATUS_SIZE);
@@ -1861,7 +1881,7 @@
*/
mask = param + 12;
- mask_len = smb_encode_path(server, mask, dir, &star);
+ mask_len = smb_encode_path(server, mask, SMB_MAXNAMELEN+1, dir, &star);
if (mask_len < 0) {
result = mask_len;
goto unlock_return;
@@ -2068,7 +2088,7 @@
int mask_len, result;
retry:
- mask_len = smb_encode_path(server, mask, dentry, NULL);
+ mask_len = smb_encode_path(server, mask, SMB_MAXNAMELEN+1, dentry, NULL);
if (mask_len < 0) {
result = mask_len;
goto out;
@@ -2146,11 +2166,9 @@
retry:
p = smb_setup_header(server, SMBgetatr, 0, 0);
- *p++ = 4;
- result = smb_encode_path(server, p, dir, NULL);
+ result = smb_simple_encode_path(server, &p, dir, NULL);
if (result < 0)
goto out;
- p += result;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
@@ -2196,7 +2214,7 @@
retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0);
- result = smb_encode_path(server, param + 6, dir, NULL);
+ result = smb_encode_path(server, param+6, SMB_MAXNAMELEN+1, dir, NULL);
if (result < 0)
goto out;
p = param + 6 + result;
@@ -2343,11 +2361,13 @@
WSET(server->packet, smb_vwv5, 0);
WSET(server->packet, smb_vwv6, 0);
WSET(server->packet, smb_vwv7, 0);
- *p++ = 4;
- result = smb_encode_path(server, p, dentry, NULL);
+ result = smb_simple_encode_path(server, &p, dentry, NULL);
if (result < 0)
goto out;
- p += result;
+ if (p + 2 > (char *)server->packet + server->packet_size) {
+ result = -ENAMETOOLONG;
+ goto out;
+ }
*p++ = 4;
*p++ = 0;
smb_setup_bcc(server, p);
@@ -2444,7 +2464,7 @@
retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0);
- result = smb_encode_path(server, param + 6, dir, NULL);
+ result = smb_encode_path(server, param+6, SMB_MAXNAMELEN+1, dir, NULL);
if (result < 0)
goto out;
p = param + 6 + result;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)