Commit 67b7626a authored by David Howells's avatar David Howells Committed by Steve French

CIFS: Make cifs_convert_address() take a const src pointer and a length

Make cifs_convert_address() take a const src pointer and a length so that all
the strlen() calls in their can be cut out and to make it unnecessary to modify
the src string.

Also return the data length from dns_resolve_server_name_to_ip() so that a
strlen() can be cut out of cifs_compose_mount_options() too.
Acked-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent f579903e
...@@ -141,7 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -141,7 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
} }
rc = dns_resolve_server_name_to_ip(*devname, &srvIP); rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) { if (rc < 0) {
cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
__func__, *devname, rc); __func__, *devname, rc);
goto compose_mount_options_err; goto compose_mount_options_err;
...@@ -150,8 +150,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -150,8 +150,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
* assuming that we have 'unc=' and 'ip=' in * assuming that we have 'unc=' and 'ip=' in
* the original sb_mountdata * the original sb_mountdata
*/ */
md_len = strlen(sb_mountdata) + strlen(srvIP) + md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12;
strlen(ref->node_name) + 12;
mountdata = kzalloc(md_len+1, GFP_KERNEL); mountdata = kzalloc(md_len+1, GFP_KERNEL);
if (mountdata == NULL) { if (mountdata == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
......
...@@ -86,8 +86,8 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); ...@@ -86,8 +86,8 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
extern int cifs_convert_address(struct sockaddr *dst, char *src); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
extern int cifs_fill_sockaddr(struct sockaddr *dst, char *src, extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
unsigned short int port); unsigned short int port);
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
......
...@@ -1543,6 +1543,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -1543,6 +1543,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
if (volume_info->UNCip && volume_info->UNC) { if (volume_info->UNCip && volume_info->UNC) {
rc = cifs_fill_sockaddr((struct sockaddr *)&addr, rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
volume_info->UNCip, volume_info->UNCip,
strlen(volume_info->UNCip),
volume_info->port); volume_info->port);
if (!rc) { if (!rc) {
/* we failed translating address */ /* we failed translating address */
......
...@@ -40,11 +40,11 @@ static const struct cred *dns_resolver_cache; ...@@ -40,11 +40,11 @@ static const struct cred *dns_resolver_cache;
* 0 - name is not IP * 0 - name is not IP
*/ */
static int static int
is_ip(char *name) is_ip(const char *name, int len)
{ {
struct sockaddr_storage ss; struct sockaddr_storage ss;
return cifs_convert_address((struct sockaddr *)&ss, name); return cifs_convert_address((struct sockaddr *)&ss, name, len);
} }
static int static int
...@@ -54,6 +54,10 @@ dns_resolver_instantiate(struct key *key, const void *data, ...@@ -54,6 +54,10 @@ dns_resolver_instantiate(struct key *key, const void *data,
int rc = 0; int rc = 0;
char *ip; char *ip;
/* make sure this looks like an address */
if (!is_ip(data, datalen))
return -EINVAL;
ip = kmalloc(datalen + 1, GFP_KERNEL); ip = kmalloc(datalen + 1, GFP_KERNEL);
if (!ip) if (!ip)
return -ENOMEM; return -ENOMEM;
...@@ -61,12 +65,6 @@ dns_resolver_instantiate(struct key *key, const void *data, ...@@ -61,12 +65,6 @@ dns_resolver_instantiate(struct key *key, const void *data,
memcpy(ip, data, datalen); memcpy(ip, data, datalen);
ip[datalen] = '\0'; ip[datalen] = '\0';
/* make sure this looks like an address */
if (!is_ip(ip)) {
kfree(ip);
return -EINVAL;
}
key->type_data.x[0] = datalen; key->type_data.x[0] = datalen;
key->payload.data = ip; key->payload.data = ip;
...@@ -93,7 +91,7 @@ struct key_type key_type_dns_resolver = { ...@@ -93,7 +91,7 @@ struct key_type key_type_dns_resolver = {
* unc - server UNC * unc - server UNC
* output: * output:
* *ip_addr - pointer to server ip, caller responcible for freeing it. * *ip_addr - pointer to server ip, caller responcible for freeing it.
* return 0 on success * return the length of the returned string on success
*/ */
int int
dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
...@@ -131,7 +129,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) ...@@ -131,7 +129,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
memcpy(name, unc+2, len); memcpy(name, unc+2, len);
name[len] = 0; name[len] = 0;
if (is_ip(name)) { if (is_ip(name, len)) {
cFYI(1, "%s: it is IP, skipping dns upcall: %s", cFYI(1, "%s: it is IP, skipping dns upcall: %s",
__func__, name); __func__, name);
data = name; data = name;
...@@ -164,7 +162,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) ...@@ -164,7 +162,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
name, name,
*ip_addr *ip_addr
); );
rc = 0; rc = len;
} else { } else {
rc = -ENOMEM; rc = -ENOMEM;
} }
......
...@@ -140,17 +140,18 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { ...@@ -140,17 +140,18 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
* Returns 0 on failure. * Returns 0 on failure.
*/ */
static int static int
cifs_inet_pton(const int address_family, const char *cp, void *dst) cifs_inet_pton(const int address_family, const char *cp, int len, void *dst)
{ {
int ret = 0; int ret = 0;
/* calculate length by finding first slash or NULL */ /* calculate length by finding first slash or NULL */
if (address_family == AF_INET) if (address_family == AF_INET)
ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); ret = in4_pton(cp, len, dst, '\\', NULL);
else if (address_family == AF_INET6) else if (address_family == AF_INET6)
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); ret = in6_pton(cp, len, dst , '\\', NULL);
cFYI(DBG2, "address conversion returned %d for %s", ret, cp); cFYI(DBG2, "address conversion returned %d for %*.*s",
ret, len, len, cp);
if (ret > 0) if (ret > 0)
ret = 1; ret = 1;
return ret; return ret;
...@@ -165,37 +166,39 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) ...@@ -165,37 +166,39 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
* Returns 0 on failure. * Returns 0 on failure.
*/ */
int int
cifs_convert_address(struct sockaddr *dst, char *src) cifs_convert_address(struct sockaddr *dst, const char *src, int len)
{ {
int rc; int rc, alen, slen;
char *pct, *endp; const char *pct;
char *endp, scope_id[13];
struct sockaddr_in *s4 = (struct sockaddr_in *) dst; struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
/* IPv4 address */ /* IPv4 address */
if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) {
s4->sin_family = AF_INET; s4->sin_family = AF_INET;
return 1; return 1;
} }
/* temporarily terminate string */ /* attempt to exclude the scope ID from the address part */
pct = strchr(src, '%'); pct = memchr(src, '%', len);
if (pct) alen = pct ? pct - src : len;
*pct = '\0';
rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
/* repair temp termination (if any) and make pct point to scopeid */
if (pct)
*pct++ = '%';
rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr);
if (!rc) if (!rc)
return rc; return rc;
s6->sin6_family = AF_INET6; s6->sin6_family = AF_INET6;
if (pct) { if (pct) {
/* grab the scope ID */
slen = len - (alen + 1);
if (slen <= 0 || slen > 12)
return 0;
memcpy(scope_id, pct + 1, slen);
scope_id[slen] = '\0';
s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
if (!*pct || *endp) if (endp != scope_id + slen)
return 0; return 0;
} }
...@@ -203,10 +206,10 @@ cifs_convert_address(struct sockaddr *dst, char *src) ...@@ -203,10 +206,10 @@ cifs_convert_address(struct sockaddr *dst, char *src)
} }
int int
cifs_fill_sockaddr(struct sockaddr *dst, char *src, cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
const unsigned short int port) const unsigned short int port)
{ {
if (!cifs_convert_address(dst, src)) if (!cifs_convert_address(dst, src, len))
return 0; return 0;
switch (dst->sa_family) { switch (dst->sa_family) {
......
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