Commit 0cfcdb1c authored by Steve French's avatar Steve French

Merge bk://cifs.bkbits.net/linux-2.5cifs

into steveft21.austin.ibm.com:/usr/src/linux-2.5cifs
parents 121dd68a de1d2468
Version 0.69
------------
Fix buffer overrun in readdir which caused intermittent kernel oopses.
Fix writepage code to release kmap on write data. Allow "-ip=" new
mount option to be passed in on parameter distinct from the first part
(server name portion of) the UNC name. Allow override of the
tcp port of the target server via new mount option "-port="
Version 0.68 Version 0.68
------------ ------------
Fix search handle leak on rewind. Fix setuid and gid so that they are Fix search handle leak on rewind. Fix setuid and gid so that they are
......
...@@ -318,6 +318,7 @@ struct file_operations cifs_file_ops = { ...@@ -318,6 +318,7 @@ struct file_operations cifs_file_ops = {
struct file_operations cifs_dir_ops = { struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir, .readdir = cifs_readdir,
.release = cifs_closedir, .release = cifs_closedir,
.read = generic_read_dir,
}; };
static void static void
......
...@@ -710,9 +710,9 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, ...@@ -710,9 +710,9 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
, nls_codepage); , nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->OldFileName[name_len] = 0; /* pad */ pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */ /* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x04; pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 = name_len2 =
cifs_strtoUCS((wchar_t *) & pSMB-> cifs_strtoUCS((wchar_t *) & pSMB->
OldFileName[name_len + 2], toName, 530, OldFileName[name_len + 2], toName, 530,
......
...@@ -56,6 +56,7 @@ struct smb_vol { ...@@ -56,6 +56,7 @@ struct smb_vol {
mode_t file_mode; mode_t file_mode;
mode_t dir_mode; mode_t dir_mode;
int rw; int rw;
unsigned short int port;
}; };
int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket); int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
...@@ -343,11 +344,7 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol) ...@@ -343,11 +344,7 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
char *value; char *value;
char *data; char *data;
vol->username = NULL; memset(vol,0,sizeof(struct smb_vol));
vol->password = NULL;
vol->domainname = NULL;
vol->UNC = NULL;
vol->UNCip = NULL;
vol->linux_uid = current->uid; /* current->euid instead? */ vol->linux_uid = current->uid; /* current->euid instead? */
vol->linux_gid = current->gid; vol->linux_gid = current->gid;
vol->rw = TRUE; vol->rw = TRUE;
...@@ -381,6 +378,15 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol) ...@@ -381,6 +378,15 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
printk(KERN_WARNING "CIFS: password too long\n"); printk(KERN_WARNING "CIFS: password too long\n");
return 1; return 1;
} }
} else if (strnicmp(data, "ip", 2) == 0) {
if (!value || !*value) {
vol->UNCip = NULL;
} else if (strnlen(value, 35) < 35) {
vol->UNCip = value;
} else {
printk(KERN_WARNING "CIFS: ip address too long\n");
return 1;
}
} else if ((strnicmp(data, "unc", 3) == 0) } else if ((strnicmp(data, "unc", 3) == 0)
|| (strnicmp(data, "target", 6) == 0) || (strnicmp(data, "target", 6) == 0)
|| (strnicmp(data, "path", 4) == 0)) { || (strnicmp(data, "path", 4) == 0)) {
...@@ -399,7 +405,6 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol) ...@@ -399,7 +405,6 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
"CIFS: UNC Path does not begin with // or \\\\ \n"); "CIFS: UNC Path does not begin with // or \\\\ \n");
return 1; return 1;
} }
vol->UNCip = &vol->UNC[2];
} else { } else {
printk(KERN_WARNING "CIFS: UNC name too long\n"); printk(KERN_WARNING "CIFS: UNC name too long\n");
return 1; return 1;
...@@ -420,22 +425,27 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol) ...@@ -420,22 +425,27 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
} else if (strnicmp(data, "uid", 3) == 0) { } else if (strnicmp(data, "uid", 3) == 0) {
if (value && *value) { if (value && *value) {
vol->linux_uid = vol->linux_uid =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} }
} else if (strnicmp(data, "gid", 3) == 0) { } else if (strnicmp(data, "gid", 3) == 0) {
if (value && *value) { if (value && *value) {
vol->linux_gid = vol->linux_gid =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} }
} else if (strnicmp(data, "file_mode", 4) == 0) { } else if (strnicmp(data, "file_mode", 4) == 0) {
if (value && *value) { if (value && *value) {
vol->file_mode = vol->file_mode =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} }
} else if (strnicmp(data, "dir_mode", 3) == 0) { } else if (strnicmp(data, "dir_mode", 3) == 0) {
if (value && *value) { if (value && *value) {
vol->dir_mode = vol->dir_mode =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
}
} else if (strnicmp(data, "port", 4) == 0) {
if (value && *value) {
vol->port =
simple_strtoul(value, &value, 0);
} }
} else if (strnicmp(data, "version", 3) == 0) { } else if (strnicmp(data, "version", 3) == 0) {
/* ignore */ /* ignore */
...@@ -458,12 +468,14 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol) ...@@ -458,12 +468,14 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n"); printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
return 1; return 1;
} }
vol->UNCip = &vol->UNC[2];
} else { } else {
printk(KERN_WARNING "CIFS: UNC name too long\n"); printk(KERN_WARNING "CIFS: UNC name too long\n");
return 1; return 1;
} }
} }
if(vol->UNCip == 0)
vol->UNCip = &vol->UNC[2];
return 0; return 0;
} }
...@@ -553,20 +565,19 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, ...@@ -553,20 +565,19 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
unsigned char *referrals = NULL; unsigned char *referrals = NULL;
if (pSesInfo->ipc_tid == 0) { if (pSesInfo->ipc_tid == 0) {
temp_unc = temp_unc = kmalloc(2 /* for slashes */ +
kmalloc(2 + strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
strnlen(pSesInfo->serverName, + 1 + 4 /* slash IPC$ */ + 2,
SERVER_NAME_LEN_WITH_NULL * 2) + 1 + GFP_KERNEL);
4 /* IPC$ */ + 1, GFP_KERNEL);
if (temp_unc == NULL) if (temp_unc == NULL)
return -ENOMEM; return -ENOMEM;
temp_unc[0] = '\\'; temp_unc[0] = '\\';
temp_unc[1] = '\\'; temp_unc[1] = '\\';
strncpy(temp_unc + 2, pSesInfo->serverName, strncpy(temp_unc + 2, pSesInfo->serverName,
SERVER_NAME_LEN_WITH_NULL * 2); SERVER_NAME_LEN_WITH_NULL * 2);
strncpy(temp_unc + 2 + strncpy(temp_unc + 2 +
strnlen(pSesInfo->serverName, strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2),
SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6); "\\IPC$", 5);
rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
cFYI(1, cFYI(1,
("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid)); ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
...@@ -670,11 +681,23 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket) ...@@ -670,11 +681,23 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
} }
psin_server->sin_family = AF_INET; psin_server->sin_family = AF_INET;
psin_server->sin_port = htons(CIFS_PORT); if(psin_server->sin_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
sizeof (struct sockaddr_in),0);
if (rc >= 0) {
return rc;
}
}
/* do not retry on the same port we just failed on */
if(psin_server->sin_port != htons(CIFS_PORT)) {
psin_server->sin_port = htons(CIFS_PORT);
rc = (*csocket)->ops->connect(*csocket, rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in),0); sizeof (struct sockaddr_in),0);
}
if (rc < 0) { if (rc < 0) {
psin_server->sin_port = htons(RFC1001_PORT); psin_server->sin_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
...@@ -703,13 +726,24 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -703,13 +726,24 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
} }
psin_server->sin6_family = AF_INET6; psin_server->sin6_family = AF_INET6;
psin_server->sin6_port = htons(CIFS_PORT); if(psin_server->sin6_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
sizeof (struct sockaddr_in6),0);
if (rc >= 0) {
return rc;
}
}
rc = (*csocket)->ops->connect(*csocket, /* do not retry on the same port we just failed on */
(struct sockaddr *) psin_server, if(psin_server->sin6_port != htons(CIFS_PORT)) {
sizeof (struct sockaddr_in6), 0 psin_server->sin6_port = htons(CIFS_PORT);
/* BB fix the timeout to be shorter - and check flags */
); rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
sizeof (struct sockaddr_in6), 0);
/* BB fix the timeout to be shorter above - and check flags */
}
if (rc < 0) { if (rc < 0) {
psin_server->sin6_port = htons(RFC1001_PORT); psin_server->sin6_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
...@@ -778,7 +812,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -778,7 +812,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
volume_info.username, &srvTcp); volume_info.username, &srvTcp);
if (srvTcp) { if (srvTcp) {
cFYI(1, ("Existing tcp session with server found ")); cFYI(1, ("Existing tcp session with server found "));
} else { /* create socket */ } else { /* create socket */
if(volume_info.port)
sin_server.sin_port = htons(volume_info.port);
rc = ipv4_connect(&sin_server, &csocket); rc = ipv4_connect(&sin_server, &csocket);
if (rc < 0) { if (rc < 0) {
cERROR(1, cERROR(1,
......
...@@ -1065,11 +1065,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1065,11 +1065,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid(); xid = GetXid();
data = kmalloc(4096, GFP_KERNEL);
pfindData = (FILE_DIRECTORY_INFO *) data;
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
data = kmalloc(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE,
GFP_KERNEL);
pfindData = (FILE_DIRECTORY_INFO *) data;
full_path = build_wildcard_path_from_dentry(file->f_dentry); full_path = build_wildcard_path_from_dentry(file->f_dentry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment