From: rmccabe@sourceware.org <rmccabe@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/cman/daemon cmanccs.c
Date: 24 Oct 2007 05:55:07 -0000 [thread overview]
Message-ID: <20071024055507.413.qmail@sourceware.org> (raw)
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: rmccabe at sourceware.org 2007-10-24 05:55:07
Modified files:
cman/daemon : cmanccs.c
Log message:
- Fix unsafe string handling:
- replace memset(s,c,n);sprintf(s,...); with snprintf with proper error checking
- don't overflow the stack if the cluster name specified in the env var is too long
- don't overflow the stack if the local nodename from uname(2) is too long
- don't overflow the stack if the local nodename specified in the env var is too long
- Don't leak the ccs descriptor in get_ccs_join_info() on errors
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/daemon/cmanccs.c.diff?cvsroot=cluster&r1=1.34&r2=1.35
--- cluster/cman/daemon/cmanccs.c 2007/10/24 03:21:45 1.34
+++ cluster/cman/daemon/cmanccs.c 2007/10/24 05:55:07 1.35
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005-2006 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -125,49 +125,60 @@
if (!ccs_get(ctree, TWO_NODE_PATH, &str)) {
two_node = atoi(str);
free(str);
- }
- else
- two_node = 0;
+ } else
+ two_node = 0;
for (i=1;;i++) {
- char path[MAX_PATH_LEN];
- int votes=0, nodeid=0;
+ char path[MAX_PATH_LEN];
+ int votes=0, nodeid=0;
+ int ret;
+
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNUM, i);
+ if (ret < 0 || (size_t) ret >= sizeof(path))
+ return -E2BIG;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NAME_PATH_BYNUM, i);
- error = ccs_get(ctree, path, &nodename);
- if (error)
- break;
+ error = ccs_get(ctree, path, &nodename);
+ if (error)
+ break;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_VOTES_PATH, nodename);
- if (!ccs_get(ctree, path, &str)) {
- votes = atoi(str);
- free(str);
- } else
- votes = 1;
+ ret = snprintf(path, sizeof(path), NODE_VOTES_PATH, nodename);
+ if (ret < 0 || ret >= sizeof(path)) {
+ error = -E2BIG;
+ goto out_err;
+ }
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NODEID_PATH, nodename);
- if (!ccs_get(ctree, path, &str)) {
- nodeid = atoi(str);
- free(str);
+ if (!ccs_get(ctree, path, &str)) {
+ votes = atoi(str);
+ free(str);
+ } else
+ votes = 1;
- }
+ ret = snprintf(path, sizeof(path), NODE_NODEID_PATH, nodename);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ goto out_err;
+ }
- if (check_nodeids && nodeid == 0) {
- char message[132];
+ if (!ccs_get(ctree, path, &str)) {
+ nodeid = atoi(str);
+ free(str);
+ }
- sprintf(message, "No node ID for %s, run 'ccs_tool addnodeids' to fix", nodename);
- log_printf(LOG_ERR, message);
- write_cman_pipe(message);
- return -1;
- }
+ if (check_nodeids && nodeid == 0) {
+ char message[132];
- P_MEMB("Got node %s from ccs (id=%d, votes=%d)\n", nodename, nodeid, votes);
- add_ccs_node(nodename, nodeid, votes, expected);
+ snprintf(message, sizeof(message),
+ "No node ID for %s, run 'ccs_tool addnodeids' to fix",
+ nodename);
+ log_printf(LOG_ERR, message);
+ write_cman_pipe(message);
+ error = -EINVAL;
+ goto out_err;
+ }
- free(nodename);
+ P_MEMB("Got node %s from ccs (id=%d, votes=%d)\n", nodename, nodeid, votes);
+ add_ccs_node(nodename, nodeid, votes, expected);
+ free(nodename);
}
if (expected)
@@ -177,6 +188,11 @@
ccs_disconnect(ctree);
return 0;
+
+out_err:
+ free(nodename);
+ ccs_disconnect(ctree);
+ return error;
}
static char *default_mcast(uint16_t cluster_id)
@@ -260,11 +276,14 @@
struct ifaddrs *ifa, *ifa_list;
struct sockaddr *sa;
int error, i;
+ int ret;
/* nodename is either from commandline or from uname */
str = NULL;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename);
+
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename);
+ if (ret < 0 || (size_t) ret >= sizeof(path))
+ return -E2BIG;
error = ccs_get(cd, path, &str);
if (!error) {
@@ -274,13 +293,14 @@
/* If nodename was from uname, try a domain-less version of it */
strcpy(nodename2, nodename);
- dot = strstr(nodename2, ".");
+ dot = strchr(nodename2, '.');
if (dot) {
*dot = '\0';
str = NULL;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename2);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename2);
+ if (ret < 0 || (size_t) ret >= sizeof(path))
+ return -E2BIG;
error = ccs_get(cd, path, &str);
if (!error) {
@@ -290,21 +310,25 @@
}
}
-
/* If nodename (from uname) is domain-less, try to match against
cluster.conf names which may have domainname specified */
for (i = 1; ; i++) {
int len;
+
str = NULL;
- memset(path, 0, 256);
- sprintf(path, "/cluster/clusternodes/clusternode[%d]/@name", i);
+ ret = snprintf(path, sizeof(path),
+ "/cluster/clusternodes/clusternode[%d]/@name", i);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
error = ccs_get(cd, path, &str);
if (error || !str)
break;
strcpy(nodename3, str);
- dot = strstr(nodename3, ".");
+ dot = strchr(nodename3, '.');
if (dot)
len = dot-nodename3;
else
@@ -328,7 +352,6 @@
return -1;
for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
-
/* Restore this */
strcpy(nodename2, nodename);
sa = ifa->ifa_addr;
@@ -341,8 +364,11 @@
goto out;
str = NULL;
- memset(path, 0, 256);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename2);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename2);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ goto out;
+ }
error = ccs_get(cd, path, &str);
if (!error) {
@@ -353,14 +379,17 @@
/* truncate this name and try again */
- dot = strstr(nodename2, ".");
+ dot = strchr(nodename2, '.');
if (!dot)
continue;
*dot = '\0';
str = NULL;
- memset(path, 0, 256);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename2);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename2);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ goto out;
+ }
error = ccs_get(cd, path, &str);
if (!error) {
@@ -376,8 +405,11 @@
goto out;
str = NULL;
- memset(path, 0, 256);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename2);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename2);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ goto out;
+ }
error = ccs_get(cd, path, &str);
if (!error) {
@@ -398,7 +430,7 @@
{
char path[MAX_PATH_LEN];
char nodename[MAX_CLUSTER_MEMBER_NAME_LEN+1];
- char *str, *name, *cname = NULL;
+ char *str, *name, *cname = NULL, *nodename_env;
int cd, error, i, vote_sum = 0, node_count = 0;
unsigned short port = 0;
@@ -420,17 +452,26 @@
if (error) {
log_printf(LOG_ERR, "cannot find cluster name in config file");
write_cman_pipe("Can't find cluster name in CCS");
- return -ENOENT;
+ error = -ENOENT;
+ goto out;
}
if (cname) {
if (strcmp(cname, str)) {
log_printf(LOG_ERR, "cluster names not equal %s %s", cname, str);
write_cman_pipe("Cluster name in CCS does not match that passed to cman_tool");
- return -ENOENT;
+ error = -ENOENT;
+ goto out;
}
}
+ if (strlen(str) >= sizeof(cluster_name)) {
+ free(str);
+ write_cman_pipe("Cluster name in CCS is too long");
+ error = -E2BIG;
+ goto out;
+ }
+
strcpy(cluster_name, str);
free(str);
@@ -444,32 +485,55 @@
}
/* our nodename */
- memset(nodename, 0, sizeof(nodename));
+ nodename_env = getenv("CMAN_NODENAME");
+ if (nodename_env != NULL) {
+ int ret;
+
+ if (strlen(nodename_env) >= sizeof(nodename)) {
+ log_printf(LOG_ERR, "Overridden node name %s is too long", nodename);
+ write_cman_pipe("Overridden node name is too long");
+ error = -E2BIG;
+ goto out;
+ }
- if (getenv("CMAN_NODENAME")) {
- strcpy(nodename, getenv("CMAN_NODENAME"));
+ strcpy(nodename, nodename_env);
log_printf(LOG_INFO, "Using override node name %s\n", nodename);
- sprintf(path, NODE_NAME_PATH_BYNAME, nodename);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNAME, nodename);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ log_printf(LOG_ERR, "Overridden node name %s is too long", nodename);
+ write_cman_pipe("Overridden node name is too long");
+ error = -E2BIG;
+ goto out;
+ }
error = ccs_get(cd, path, &str);
if (!error) {
free(str);
- }
- else {
+ } else {
log_printf(LOG_ERR, "Overridden node name %s is not in CCS", nodename);
write_cman_pipe("Overridden node name is not in CCS");
- return -ENOENT;
+ error = -ENOENT;
+ goto out;
}
- }
- else {
+ } else {
struct utsname utsname;
+
error = uname(&utsname);
if (error) {
log_printf(LOG_ERR, "cannot get node name, uname failed");
write_cman_pipe("Can't determine local node name");
- return -ENOENT;
+ error = -ENOENT;
+ goto out;
+ }
+
+ if (strlen(utsname.nodename) >= sizeof(nodename)) {
+ log_printf(LOG_ERR, "node name from uname is too long");
+ write_cman_pipe("Can't determine local node name");
+ error = -E2BIG;
+ goto out;
}
+
strcpy(nodename, utsname.nodename);
}
@@ -480,9 +544,15 @@
log_printf(LOG_ERR, "local node name \"%s\" not found in cluster.conf",
nodename);
write_cman_pipe("Can't find local node name in cluster.conf");
- return -ENOENT;
+ error = -ENOENT;
+ goto out;
}
+
nodenames[0] = strdup(nodename);
+ if (nodenames[0] == NULL) {
+ error = -ENOMEM;
+ goto out;
+ }
expected_votes = 0;
if (getenv("CMAN_EXPECTEDVOTES")) {
@@ -499,9 +569,14 @@
/* Sum node votes for expected */
if (expected_votes == 0) {
for (i = 1; ; i++) {
+ int ret;
+
name = NULL;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NAME_PATH_BYNUM, i);
+ ret = snprintf(path, sizeof(path), NODE_NAME_PATH_BYNUM, i);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
error = ccs_get(cd, path, &name);
if (error || !name)
@@ -509,10 +584,14 @@
node_count++;
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_VOTES_PATH, name);
+ ret = snprintf(path, sizeof(path), NODE_VOTES_PATH, name);
free(name);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
+
error = ccs_get(cd, path, &str);
if (error)
vote_sum++;
@@ -520,7 +599,8 @@
if (atoi(str) < 0) {
log_printf(LOG_ERR, "negative votes not allowed");
write_cman_pipe("Found negative votes for this node in CCS");
- return -EINVAL;
+ error = -EINVAL;
+ goto out;
}
vote_sum += atoi(str);
free(str);
@@ -572,8 +652,12 @@
}
if (!votes) {
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_VOTES_PATH, nodename);
+ int ret = snprintf(path, sizeof(path), NODE_VOTES_PATH, nodename);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ log_printf(LOG_ERR, "unable to find votes for %s", nodename);
+ write_cman_pipe("Unable to find votes for node in CCS");
+ return -E2BIG;
+ }
error = ccs_get(cd, path, &str);
if (!error) {
@@ -599,13 +683,14 @@
}
if (!nodeid) {
- memset(path, 0, MAX_PATH_LEN);
- sprintf(path, NODE_NODEID_PATH, nodename);
+ int ret = snprintf(path, sizeof(path), NODE_NODEID_PATH, nodename);
- error = ccs_get(cd, path, &str);
- if (!error) {
- nodeid = atoi(str);
- free(str);
+ if (ret >= 0 && (size_t) ret < sizeof(path)) {
+ error = ccs_get(cd, path, &str);
+ if (!error) {
+ nodeid = atoi(str);
+ free(str);
+ }
}
}
@@ -638,35 +723,44 @@
/* Get all alternative node names */
num_nodenames = 1;
- memset(path, 0, MAX_PATH_LEN);
-
-
for (i = 1; ; i++) {
- str = NULL;
- sprintf(path, NODE_ALTNAMES_PATH, nodename, i);
+ int ret = snprintf(path, sizeof(path), NODE_ALTNAMES_PATH, nodename, i);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
+ str = NULL;
error = ccs_get(cd, path, &str);
if (error || !str)
break;
nodenames[i] = str;
- sprintf(path, NODE_ALTNAMES_PORT, nodename, i);
+ ret = snprintf(path, sizeof(path), NODE_ALTNAMES_PORT, nodename, i);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
+
error = ccs_get(cd, path, &str);
if (error || !str) {
portnums[i] = portnums[0];
- }
- else {
+ } else {
portnums[i] = atoi(str);
free(str);
}
- sprintf(path, NODE_ALTNAMES_MCAST, nodename, i);
+ ret = snprintf(path, sizeof(path), NODE_ALTNAMES_MCAST, nodename, i);
+ if (ret < 0 || (size_t) ret >= sizeof(path)) {
+ error = -E2BIG;
+ break;
+ }
+
error = ccs_get(cd, path, &str);
if (error || !str) {
mcast[i] = mcast_name;
- }
- else {
+ } else {
mcast[i] = str;
}
@@ -686,7 +780,8 @@
"votes of 1 (node_count=%d vote_sum=%d)",
node_count, vote_sum);
write_cman_pipe("two_node set but there are more than 2 nodes");
- return -EINVAL;
+ error = -EINVAL;
+ goto out;
}
if (votes != 1) {
@@ -694,13 +789,17 @@
"nodes with one vote each and expected "
"votes of 1 (votes=%d)", votes);
write_cman_pipe("two_node set but votes not set to 1");
- return -EINVAL;
+ error = -EINVAL;
+ goto out;
}
}
}
+ error = 0;
+
+out:
ccs_disconnect(cd);
- return 0;
+ return error;
}
next reply other threads:[~2007-10-24 5:55 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-24 5:55 rmccabe [this message]
2007-10-24 7:27 ` [Cluster-devel] cluster/cman/daemon cmanccs.c Fabio Massimo Di Nitto
-- strict thread matches above, loose matches on Subject: below --
2007-11-05 16:03 pcaulfield
2007-10-24 5:58 rmccabe
2007-10-24 3:21 fabbione
2007-10-24 3:21 fabbione
2007-10-24 3:20 fabbione
2007-08-17 7:51 pcaulfield
2007-08-03 10:49 pcaulfield
2007-08-03 7:35 pcaulfield
2007-05-23 10:31 pcaulfield
2007-03-15 11:12 pcaulfield
2007-03-15 9:27 pcaulfield
2007-01-02 15:17 pcaulfield
2007-01-02 15:04 pcaulfield
2006-12-15 15:17 pcaulfield
2006-12-15 13:43 pcaulfield
2006-11-30 10:47 pcaulfield
2006-11-30 10:46 pcaulfield
2006-07-03 8:51 pcaulfield
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071024055507.413.qmail@sourceware.org \
--to=rmccabe@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.