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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).