* [PATCH 1/1] data race in bindresvport_sa
@ 2013-11-20 16:49 Susant Sahani
2013-11-20 16:49 ` [PATCH] __nc_error() does not check return value from malloc Susant Sahani
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Susant Sahani @ 2013-11-20 16:49 UTC (permalink / raw)
To: Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/bindresvport.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/bindresvport.c b/src/bindresvport.c
index 6ce3e81..d26d754 100644
--- a/src/bindresvport.c
+++ b/src/bindresvport.c
@@ -46,6 +46,7 @@
#include <rpc/rpc.h>
#include <string.h>
+#include <reentrant.h>
/*
* Bind a socket to a privileged IP port
@@ -79,17 +80,23 @@ bindresvport_sa(sd, sa)
u_int16_t *portp;
static u_int16_t port;
static short startport = STARTPORT;
+ static pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
socklen_t salen;
- int nports = ENDPORT - startport + 1;
+ int nports;
int endport = ENDPORT;
int i;
+ mutex_lock(&port_lock);
+ nports = ENDPORT - startport + 1;
+
if (sa == NULL) {
salen = sizeof(myaddr);
sa = (struct sockaddr *)&myaddr;
- if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
- return -1; /* errno is correctly set */
+ if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
+ mutex_unlock(&port_lock);
+ return -1; /* errno is correctly set */
+ }
af = myaddr.ss_family;
} else
@@ -112,6 +119,7 @@ bindresvport_sa(sd, sa)
#endif
default:
errno = EPFNOSUPPORT;
+ mutex_unlock(&port_lock);
return (-1);
}
sa->sa_family = af;
@@ -137,6 +145,8 @@ bindresvport_sa(sd, sa)
port = LOWPORT + port % (STARTPORT - LOWPORT);
goto again;
}
+ mutex_unlock(&port_lock);
+
return (res);
}
#else
--
1.8.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH] __nc_error() does not check return value from malloc
2013-11-20 16:49 [PATCH 1/1] data race in bindresvport_sa Susant Sahani
@ 2013-11-20 16:49 ` Susant Sahani
2013-11-25 20:09 ` [Libtirpc-devel] " Steve Dickson
2013-11-20 16:49 ` [PATCH 1/1] race in clnt_vc_create Susant Sahani
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Susant Sahani @ 2013-11-20 16:49 UTC (permalink / raw)
To: Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/getnetconfig.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/getnetconfig.c b/src/getnetconfig.c
index af4a484..2460a6e 100644
--- a/src/getnetconfig.c
+++ b/src/getnetconfig.c
@@ -146,7 +146,8 @@ __nc_error()
return (&nc_error);
}
if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
- nc_addr = (int *)malloc(sizeof (int));
+ if((nc_addr = (int *)malloc(sizeof (int))) == NULL)
+ return (&nc_error);
if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
if (nc_addr)
free(nc_addr);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/1] race in clnt_vc_create
2013-11-20 16:49 [PATCH 1/1] data race in bindresvport_sa Susant Sahani
2013-11-20 16:49 ` [PATCH] __nc_error() does not check return value from malloc Susant Sahani
@ 2013-11-20 16:49 ` Susant Sahani
2013-11-20 16:49 ` [PATCH 1/1] Race in getnetconfig Susant Sahani
2013-11-22 16:28 ` [PATCH 1/1] data race in bindresvport_sa Steve Dickson
3 siblings, 0 replies; 8+ messages in thread
From: Susant Sahani @ 2013-11-20 16:49 UTC (permalink / raw)
To: Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/clnt_vc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/clnt_vc.c b/src/clnt_vc.c
index 2eab9e4..bf3f13c 100644
--- a/src/clnt_vc.c
+++ b/src/clnt_vc.c
@@ -173,14 +173,17 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
struct timeval now;
struct rpc_msg call_msg;
static u_int32_t disrupt;
+ static pthread_mutex_t disrupt_lock = PTHREAD_MUTEX_INITIALIZER;
sigset_t mask;
sigset_t newmask;
struct sockaddr_storage ss;
socklen_t slen;
struct __rpc_sockinfo si;
+ mutex_lock(&disrupt_lock);
if (disrupt == 0)
disrupt = (u_int32_t)(long)raddr;
+ mutex_unlock(&disrupt_lock);
cl = (CLIENT *)mem_alloc(sizeof (*cl));
ct = (struct ct_data *)mem_alloc(sizeof (*ct));
@@ -270,7 +273,9 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
* Initialize call message
*/
(void)gettimeofday(&now, NULL);
+ mutex_lock(&disrupt_lock);
call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
+ mutex_unlock(&disrupt_lock);
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = (u_int32_t)prog;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/1] Race in getnetconfig
2013-11-20 16:49 [PATCH 1/1] data race in bindresvport_sa Susant Sahani
2013-11-20 16:49 ` [PATCH] __nc_error() does not check return value from malloc Susant Sahani
2013-11-20 16:49 ` [PATCH 1/1] race in clnt_vc_create Susant Sahani
@ 2013-11-20 16:49 ` Susant Sahani
2013-11-22 16:28 ` [PATCH 1/1] data race in bindresvport_sa Steve Dickson
3 siblings, 0 replies; 8+ messages in thread
From: Susant Sahani @ 2013-11-20 16:49 UTC (permalink / raw)
To: Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/getnetconfig.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/src/getnetconfig.c b/src/getnetconfig.c
index 2460a6e..9c21562 100644
--- a/src/getnetconfig.c
+++ b/src/getnetconfig.c
@@ -120,6 +120,7 @@ static struct netconfig *dup_ncp(struct netconfig *);
static FILE *nc_file; /* for netconfig db */
static struct netconfig_info ni = { 0, 0, NULL, NULL};
+static pthread_mutex_t nc_db_lock = PTHREAD_MUTEX_INITIALIZER;
#define MAXNETCONFIGLINE 1000
@@ -192,14 +193,17 @@ setnetconfig()
* For multiple calls, i.e. nc_file is not NULL, we just return the
* handle without reopening the netconfig db.
*/
+ mutex_lock(&nc_db_lock);
ni.ref++;
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
nc_vars->valid = NC_VALID;
nc_vars->flag = 0;
nc_vars->nc_configs = ni.head;
+ mutex_unlock(&nc_db_lock);
return ((void *)nc_vars);
}
ni.ref--;
+ mutex_unlock(&nc_db_lock);
nc_error = NC_NONETCONFIG;
free(nc_vars);
return (NULL);
@@ -222,12 +226,15 @@ void *handlep;
char *stringp; /* tmp string pointer */
struct netconfig_list *list;
struct netconfig *np;
+ struct netconfig *result;
/*
* Verify that handle is valid
*/
+ mutex_lock(&nc_db_lock);
if (ncp == NULL || nc_file == NULL) {
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
@@ -244,11 +251,14 @@ void *handlep;
if (ncp->flag == 0) { /* first time */
ncp->flag = 1;
ncp->nc_configs = ni.head;
- if (ncp->nc_configs != NULL) /* entry already exist */
+ if (ncp->nc_configs != NULL) /* entry already exist */ {
+ mutex_unlock(&nc_db_lock);
return(ncp->nc_configs->ncp);
+ }
}
else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
ncp->nc_configs = ncp->nc_configs->next;
+ mutex_unlock(&nc_db_lock);
return(ncp->nc_configs->ncp);
}
@@ -256,16 +266,22 @@ void *handlep;
* If we cannot find the entry in the list and is end of file,
* we give up.
*/
- if (ni.eof == 1) return(NULL);
+ if (ni.eof == 1) {
+ mutex_unlock(&nc_db_lock);
+ return(NULL);
+ }
break;
default:
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
stringp = (char *) malloc(MAXNETCONFIGLINE);
- if (stringp == NULL)
+ if (stringp == NULL) {
+ mutex_unlock(&nc_db_lock);
return (NULL);
+ }
#ifdef MEM_CHK
if (malloc_verify() == 0) {
@@ -281,6 +297,7 @@ void *handlep;
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
free(stringp);
ni.eof = 1;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
} while (*stringp == '#');
@@ -288,12 +305,14 @@ void *handlep;
list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
if (list == NULL) {
free(stringp);
+ mutex_unlock(&nc_db_lock);
return(NULL);
}
np = (struct netconfig *) malloc(sizeof (struct netconfig));
if (np == NULL) {
free(stringp);
free(list);
+ mutex_unlock(&nc_db_lock);
return(NULL);
}
list->ncp = np;
@@ -304,6 +323,7 @@ void *handlep;
free(stringp);
free(np);
free(list);
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
else {
@@ -321,7 +341,9 @@ void *handlep;
ni.tail = ni.tail->next;
}
ncp->nc_configs = ni.tail;
- return(ni.tail->ncp);
+ result = ni.tail->ncp;
+ mutex_unlock(&nc_db_lock);
+ return result;
}
}
@@ -355,7 +377,9 @@ void *handlep;
nc_handlep->valid = NC_INVALID;
nc_handlep->flag = 0;
nc_handlep->nc_configs = NULL;
+ mutex_lock(&nc_db_lock);
if (--ni.ref > 0) {
+ mutex_unlock(&nc_db_lock);
free(nc_handlep);
return(0);
}
@@ -377,9 +401,11 @@ void *handlep;
q = p;
}
free(nc_handlep);
-
- fclose(nc_file);
+ if(nc_file != NULL) {
+ fclose(nc_file);
+ }
nc_file = NULL;
+ mutex_unlock(&nc_db_lock);
return (0);
}
@@ -427,16 +453,21 @@ getnetconfigent(netid)
* If all the netconfig db has been read and placed into the list and
* there is no match for the netid, return NULL.
*/
+ mutex_lock(&nc_db_lock);
if (ni.head != NULL) {
for (list = ni.head; list; list = list->next) {
if (strcmp(list->ncp->nc_netid, netid) == 0) {
- return(dup_ncp(list->ncp));
+ ncp = dup_ncp(list->ncp);
+ mutex_unlock(&nc_db_lock);
+ return ncp;
}
}
- if (ni.eof == 1) /* that's all the entries */
- return(NULL);
+ if (ni.eof == 1) { /* that's all the entries */
+ mutex_unlock(&nc_db_lock);
+ return(NULL);
+ }
}
-
+ mutex_unlock(&nc_db_lock);
if ((file = fopen(NETCONFIG, "r")) == NULL) {
nc_error = NC_NONETCONFIG;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] data race in bindresvport_sa
2013-11-20 16:49 [PATCH 1/1] data race in bindresvport_sa Susant Sahani
` (2 preceding siblings ...)
2013-11-20 16:49 ` [PATCH 1/1] Race in getnetconfig Susant Sahani
@ 2013-11-22 16:28 ` Steve Dickson
2013-11-25 17:49 ` Susant Sahani
3 siblings, 1 reply; 8+ messages in thread
From: Steve Dickson @ 2013-11-22 16:28 UTC (permalink / raw)
To: Susant Sahani, Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
Hello,
Would it be possible to get a little better description as
to what this patch does and why its needed...
"data race in bindresvport_sa" have very little
meaning, at least to me...
More comments below...
On 20/11/13 11:49, Susant Sahani wrote:
> Signed-off-by: Susant Sahani <ssahani@redhat.com>
> ---
> src/bindresvport.c | 16 +++++++++++++---
> 1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/src/bindresvport.c b/src/bindresvport.c
> index 6ce3e81..d26d754 100644
> --- a/src/bindresvport.c
> +++ b/src/bindresvport.c
> @@ -46,6 +46,7 @@
> #include <rpc/rpc.h>
>
> #include <string.h>
> +#include <reentrant.h>
>
> /*
> * Bind a socket to a privileged IP port
> @@ -79,17 +80,23 @@ bindresvport_sa(sd, sa)
> u_int16_t *portp;
> static u_int16_t port;
> static short startport = STARTPORT;
> + static pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
How come you define this mutex statically instead in src/mt_misc.c
like the rest of the mutexes?
Would you mind moving this (and the other two in the patches)
to src/mt_misc.c and added a commit talking about what they
are protecting
tia!
steved.
> socklen_t salen;
> - int nports = ENDPORT - startport + 1;
> + int nports;
> int endport = ENDPORT;
> int i;
>
> + mutex_lock(&port_lock);
> + nports = ENDPORT - startport + 1;
> +
> if (sa == NULL) {
> salen = sizeof(myaddr);
> sa = (struct sockaddr *)&myaddr;
>
> - if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
> - return -1; /* errno is correctly set */
> + if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
> + mutex_unlock(&port_lock);
> + return -1; /* errno is correctly set */
> + }
>
> af = myaddr.ss_family;
> } else
> @@ -112,6 +119,7 @@ bindresvport_sa(sd, sa)
> #endif
> default:
> errno = EPFNOSUPPORT;
> + mutex_unlock(&port_lock);
> return (-1);
> }
> sa->sa_family = af;
> @@ -137,6 +145,8 @@ bindresvport_sa(sd, sa)
> port = LOWPORT + port % (STARTPORT - LOWPORT);
> goto again;
> }
> + mutex_unlock(&port_lock);
> +
> return (res);
> }
> #else
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] data race in bindresvport_sa
2013-11-22 16:28 ` [PATCH 1/1] data race in bindresvport_sa Steve Dickson
@ 2013-11-25 17:49 ` Susant Sahani
2013-11-25 20:11 ` [Libtirpc-devel] " Steve Dickson
0 siblings, 1 reply; 8+ messages in thread
From: Susant Sahani @ 2013-11-25 17:49 UTC (permalink / raw)
To: Steve Dickson, Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
[-- Attachment #1: Type: text/plain, Size: 2665 bytes --]
Hi Steved,
I am sorry not for giving proper description . I have addressed
your comments attached the patches .
Thanks,
Susant
On 11/22/2013 09:58 PM, Steve Dickson wrote:
> Hello,
>
> Would it be possible to get a little better description as
> to what this patch does and why its needed...
> "data race in bindresvport_sa" have very little
> meaning, at least to me...
>
> More comments below...
>
> On 20/11/13 11:49, Susant Sahani wrote:
>> Signed-off-by: Susant Sahani <ssahani@redhat.com>
>> ---
>> src/bindresvport.c | 16 +++++++++++++---
>> 1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/src/bindresvport.c b/src/bindresvport.c
>> index 6ce3e81..d26d754 100644
>> --- a/src/bindresvport.c
>> +++ b/src/bindresvport.c
>> @@ -46,6 +46,7 @@
>> #include <rpc/rpc.h>
>>
>> #include <string.h>
>> +#include <reentrant.h>
>>
>> /*
>> * Bind a socket to a privileged IP port
>> @@ -79,17 +80,23 @@ bindresvport_sa(sd, sa)
>> u_int16_t *portp;
>> static u_int16_t port;
>> static short startport = STARTPORT;
>> + static pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
> How come you define this mutex statically instead in src/mt_misc.c
> like the rest of the mutexes?
>
> Would you mind moving this (and the other two in the patches)
> to src/mt_misc.c and added a commit talking about what they
> are protecting
>
> tia!
>
> steved.
>
>> socklen_t salen;
>> - int nports = ENDPORT - startport + 1;
>> + int nports;
>> int endport = ENDPORT;
>> int i;
>>
>> + mutex_lock(&port_lock);
>> + nports = ENDPORT - startport + 1;
>> +
>> if (sa == NULL) {
>> salen = sizeof(myaddr);
>> sa = (struct sockaddr *)&myaddr;
>>
>> - if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
>> - return -1; /* errno is correctly set */
>> + if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
>> + mutex_unlock(&port_lock);
>> + return -1; /* errno is correctly set */
>> + }
>>
>> af = myaddr.ss_family;
>> } else
>> @@ -112,6 +119,7 @@ bindresvport_sa(sd, sa)
>> #endif
>> default:
>> errno = EPFNOSUPPORT;
>> + mutex_unlock(&port_lock);
>> return (-1);
>> }
>> sa->sa_family = af;
>> @@ -137,6 +145,8 @@ bindresvport_sa(sd, sa)
>> port = LOWPORT + port % (STARTPORT - LOWPORT);
>> goto again;
>> }
>> + mutex_unlock(&port_lock);
>> +
>> return (res);
>> }
>> #else
>>
[-- Attachment #2: 0001-Race-conditions-in-getnetconfig.patch --]
[-- Type: text/x-patch, Size: 6208 bytes --]
>From 37ce9e21d64f98e79be9da4415a78cb4f644737f Mon Sep 17 00:00:00 2001
From: Susant Sahani <ssahani@redhat.com>
Date: Sat, 23 Nov 2013 13:07:14 +0530
Subject: [PATCH 1/3] Race conditions in getnetconfig
The clnt_* functions are *not* thread safe. Race conditions are caused
by the functions setnetconfig , getnetconfig, endnetconfig and
getnetconfigent that accesses global static data nc_file and ni which
are defined in the file getnetconfig are *not* protected by any mutex.
When more than one thread access them the variables become a nonlocal
side effect . These race conditions causing process to give undesired
behavior and leading to crash on file operations mostly on fclose. By
introducing the mutex nc_db_lock the netconfig database is synchronized
and prevented from crash.
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/getnetconfig.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
src/mt_misc.c | 3 +++
2 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/src/getnetconfig.c b/src/getnetconfig.c
index af4a484..3d9a9ea 100644
--- a/src/getnetconfig.c
+++ b/src/getnetconfig.c
@@ -120,6 +120,7 @@ static struct netconfig *dup_ncp(struct netconfig *);
static FILE *nc_file; /* for netconfig db */
static struct netconfig_info ni = { 0, 0, NULL, NULL};
+extern pthread_mutex_t nc_db_lock;
#define MAXNETCONFIGLINE 1000
@@ -191,14 +192,17 @@ setnetconfig()
* For multiple calls, i.e. nc_file is not NULL, we just return the
* handle without reopening the netconfig db.
*/
+ mutex_lock(&nc_db_lock);
ni.ref++;
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
nc_vars->valid = NC_VALID;
nc_vars->flag = 0;
nc_vars->nc_configs = ni.head;
+ mutex_unlock(&nc_db_lock);
return ((void *)nc_vars);
}
ni.ref--;
+ mutex_unlock(&nc_db_lock);
nc_error = NC_NONETCONFIG;
free(nc_vars);
return (NULL);
@@ -221,12 +225,15 @@ void *handlep;
char *stringp; /* tmp string pointer */
struct netconfig_list *list;
struct netconfig *np;
+ struct netconfig *result;
/*
* Verify that handle is valid
*/
+ mutex_lock(&nc_db_lock);
if (ncp == NULL || nc_file == NULL) {
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
@@ -243,11 +250,14 @@ void *handlep;
if (ncp->flag == 0) { /* first time */
ncp->flag = 1;
ncp->nc_configs = ni.head;
- if (ncp->nc_configs != NULL) /* entry already exist */
+ if (ncp->nc_configs != NULL) /* entry already exist */ {
+ mutex_unlock(&nc_db_lock);
return(ncp->nc_configs->ncp);
+ }
}
else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
ncp->nc_configs = ncp->nc_configs->next;
+ mutex_unlock(&nc_db_lock);
return(ncp->nc_configs->ncp);
}
@@ -255,16 +265,22 @@ void *handlep;
* If we cannot find the entry in the list and is end of file,
* we give up.
*/
- if (ni.eof == 1) return(NULL);
+ if (ni.eof == 1) {
+ mutex_unlock(&nc_db_lock);
+ return(NULL);
+ }
break;
default:
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
stringp = (char *) malloc(MAXNETCONFIGLINE);
- if (stringp == NULL)
+ if (stringp == NULL) {
+ mutex_unlock(&nc_db_lock);
return (NULL);
+ }
#ifdef MEM_CHK
if (malloc_verify() == 0) {
@@ -280,6 +296,7 @@ void *handlep;
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
free(stringp);
ni.eof = 1;
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
} while (*stringp == '#');
@@ -287,12 +304,14 @@ void *handlep;
list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
if (list == NULL) {
free(stringp);
+ mutex_unlock(&nc_db_lock);
return(NULL);
}
np = (struct netconfig *) malloc(sizeof (struct netconfig));
if (np == NULL) {
free(stringp);
free(list);
+ mutex_unlock(&nc_db_lock);
return(NULL);
}
list->ncp = np;
@@ -303,6 +322,7 @@ void *handlep;
free(stringp);
free(np);
free(list);
+ mutex_unlock(&nc_db_lock);
return (NULL);
}
else {
@@ -320,7 +340,9 @@ void *handlep;
ni.tail = ni.tail->next;
}
ncp->nc_configs = ni.tail;
- return(ni.tail->ncp);
+ result = ni.tail->ncp;
+ mutex_unlock(&nc_db_lock);
+ return result;
}
}
@@ -354,7 +376,9 @@ void *handlep;
nc_handlep->valid = NC_INVALID;
nc_handlep->flag = 0;
nc_handlep->nc_configs = NULL;
+ mutex_lock(&nc_db_lock);
if (--ni.ref > 0) {
+ mutex_unlock(&nc_db_lock);
free(nc_handlep);
return(0);
}
@@ -376,9 +400,11 @@ void *handlep;
q = p;
}
free(nc_handlep);
-
- fclose(nc_file);
+ if(nc_file != NULL) {
+ fclose(nc_file);
+ }
nc_file = NULL;
+ mutex_unlock(&nc_db_lock);
return (0);
}
@@ -426,16 +452,21 @@ getnetconfigent(netid)
* If all the netconfig db has been read and placed into the list and
* there is no match for the netid, return NULL.
*/
+ mutex_lock(&nc_db_lock);
if (ni.head != NULL) {
for (list = ni.head; list; list = list->next) {
if (strcmp(list->ncp->nc_netid, netid) == 0) {
- return(dup_ncp(list->ncp));
+ ncp = dup_ncp(list->ncp);
+ mutex_unlock(&nc_db_lock);
+ return ncp;
}
}
- if (ni.eof == 1) /* that's all the entries */
- return(NULL);
+ if (ni.eof == 1) { /* that's all the entries */
+ mutex_unlock(&nc_db_lock);
+ return(NULL);
+ }
}
-
+ mutex_unlock(&nc_db_lock);
if ((file = fopen(NETCONFIG, "r")) == NULL) {
nc_error = NC_NONETCONFIG;
diff --git a/src/mt_misc.c b/src/mt_misc.c
index fe12c31..b24c130 100644
--- a/src/mt_misc.c
+++ b/src/mt_misc.c
@@ -91,6 +91,9 @@ pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER;
/* serializes calls to public key routines */
pthread_mutex_t serialize_pkey = PTHREAD_MUTEX_INITIALIZER;
+/* protects global variables ni and nc_file (getnetconfig.c) */
+pthread_mutex_t nc_db_lock = PTHREAD_MUTEX_INITIALIZER;
+
#undef rpc_createerr
struct rpc_createerr rpc_createerr;
--
1.8.4.2
[-- Attachment #3: 0002-Race-condition-in-bindresvport.patch --]
[-- Type: text/x-patch, Size: 2833 bytes --]
>From 08af7bdaf61fc69b5dbc6136d8311d51b586ed63 Mon Sep 17 00:00:00 2001
From: Susant Sahani <ssahani@redhat.com>
Date: Sat, 23 Nov 2013 13:10:32 +0530
Subject: [PATCH 2/3] Race condition in bindresvport
The function clnt_create is *not* thread safe . Race conditions in
the function bindresvport that accesses static data port and startport,
which are *not* protected by any mutex. When more than one thread
access them the variables become a nonlocal side effect. These race conditions
can lead to undesired behaviour . By introducing the mutex port_lock
the function bindresvport is serialized.
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/bindresvport.c | 16 +++++++++++++---
src/mt_misc.c | 3 +++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/bindresvport.c b/src/bindresvport.c
index 6ce3e81..910056e 100644
--- a/src/bindresvport.c
+++ b/src/bindresvport.c
@@ -46,6 +46,7 @@
#include <rpc/rpc.h>
#include <string.h>
+#include <reentrant.h>
/*
* Bind a socket to a privileged IP port
@@ -79,17 +80,23 @@ bindresvport_sa(sd, sa)
u_int16_t *portp;
static u_int16_t port;
static short startport = STARTPORT;
+ extern pthread_mutex_t port_lock;
socklen_t salen;
- int nports = ENDPORT - startport + 1;
+ int nports;
int endport = ENDPORT;
int i;
+ mutex_lock(&port_lock);
+ nports = ENDPORT - startport + 1;
+
if (sa == NULL) {
salen = sizeof(myaddr);
sa = (struct sockaddr *)&myaddr;
- if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
- return -1; /* errno is correctly set */
+ if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
+ mutex_unlock(&port_lock);
+ return -1; /* errno is correctly set */
+ }
af = myaddr.ss_family;
} else
@@ -112,6 +119,7 @@ bindresvport_sa(sd, sa)
#endif
default:
errno = EPFNOSUPPORT;
+ mutex_unlock(&port_lock);
return (-1);
}
sa->sa_family = af;
@@ -137,6 +145,8 @@ bindresvport_sa(sd, sa)
port = LOWPORT + port % (STARTPORT - LOWPORT);
goto again;
}
+ mutex_unlock(&port_lock);
+
return (res);
}
#else
diff --git a/src/mt_misc.c b/src/mt_misc.c
index b24c130..ddbb0a5 100644
--- a/src/mt_misc.c
+++ b/src/mt_misc.c
@@ -94,6 +94,9 @@ pthread_mutex_t serialize_pkey = PTHREAD_MUTEX_INITIALIZER;
/* protects global variables ni and nc_file (getnetconfig.c) */
pthread_mutex_t nc_db_lock = PTHREAD_MUTEX_INITIALIZER;
+/* protects static port and startport (bindresvport.c) */
+pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
+
#undef rpc_createerr
struct rpc_createerr rpc_createerr;
--
1.8.4.2
[-- Attachment #4: 0003-Race-in-Race-in-clnt_vc_create.patch --]
[-- Type: text/x-patch, Size: 2229 bytes --]
>From f850621962cb57c7bebfc93bd28db1f26be213aa Mon Sep 17 00:00:00 2001
From: Susant Sahani <ssahani@redhat.com>
Date: Sat, 23 Nov 2013 13:12:59 +0530
Subject: [PATCH 3/3] Race in Race in clnt_vc_create
The function clnt_create is *not* thread safe. Race conditions in the
function clnt_vc_create that accesses static data disrupt, which is
*not* protected by any mutex. When more than one thread access it
it has become a nonlocal side effect . This race conditions can lead to
undesired behaviour . By introducing the mutex disrupt_lock
the function clnt_vc_create is serialized
Signed-off-by: Susant Sahani <ssahani@redhat.com>
---
src/clnt_vc.c | 5 +++++
src/mt_misc.c | 3 +++
2 files changed, 8 insertions(+)
diff --git a/src/clnt_vc.c b/src/clnt_vc.c
index 2eab9e4..cbbfc58 100644
--- a/src/clnt_vc.c
+++ b/src/clnt_vc.c
@@ -173,14 +173,17 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
struct timeval now;
struct rpc_msg call_msg;
static u_int32_t disrupt;
+ extern pthread_mutex_t disrupt_lock;
sigset_t mask;
sigset_t newmask;
struct sockaddr_storage ss;
socklen_t slen;
struct __rpc_sockinfo si;
+ mutex_lock(&disrupt_lock);
if (disrupt == 0)
disrupt = (u_int32_t)(long)raddr;
+ mutex_unlock(&disrupt_lock);
cl = (CLIENT *)mem_alloc(sizeof (*cl));
ct = (struct ct_data *)mem_alloc(sizeof (*ct));
@@ -270,7 +273,9 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
* Initialize call message
*/
(void)gettimeofday(&now, NULL);
+ mutex_lock(&disrupt_lock);
call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
+ mutex_unlock(&disrupt_lock);
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = (u_int32_t)prog;
diff --git a/src/mt_misc.c b/src/mt_misc.c
index ddbb0a5..d459dec 100644
--- a/src/mt_misc.c
+++ b/src/mt_misc.c
@@ -97,6 +97,9 @@ pthread_mutex_t nc_db_lock = PTHREAD_MUTEX_INITIALIZER;
/* protects static port and startport (bindresvport.c) */
pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
+/* protects static disrupt (clnt_vc.c) */
+pthread_mutex_t disrupt_lock = PTHREAD_MUTEX_INITIALIZER;
+
#undef rpc_createerr
struct rpc_createerr rpc_createerr;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Libtirpc-devel] [PATCH] __nc_error() does not check return value from malloc
2013-11-20 16:49 ` [PATCH] __nc_error() does not check return value from malloc Susant Sahani
@ 2013-11-25 20:09 ` Steve Dickson
0 siblings, 0 replies; 8+ messages in thread
From: Steve Dickson @ 2013-11-25 20:09 UTC (permalink / raw)
To: Susant Sahani, Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
On 20/11/13 11:49, Susant Sahani wrote:
> Signed-off-by: Susant Sahani <ssahani@redhat.com>
Committed....
steved.
> ---
> src/getnetconfig.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/src/getnetconfig.c b/src/getnetconfig.c
> index af4a484..2460a6e 100644
> --- a/src/getnetconfig.c
> +++ b/src/getnetconfig.c
> @@ -146,7 +146,8 @@ __nc_error()
> return (&nc_error);
> }
> if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
> - nc_addr = (int *)malloc(sizeof (int));
> + if((nc_addr = (int *)malloc(sizeof (int))) == NULL)
> + return (&nc_error);
> if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
> if (nc_addr)
> free(nc_addr);
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Libtirpc-devel] [PATCH 1/1] data race in bindresvport_sa
2013-11-25 17:49 ` Susant Sahani
@ 2013-11-25 20:11 ` Steve Dickson
0 siblings, 0 replies; 8+ messages in thread
From: Steve Dickson @ 2013-11-25 20:11 UTC (permalink / raw)
To: Susant Sahani, Libtirpc-devel Mailing List; +Cc: Linux NFS Mailing list
On 25/11/13 12:49, Susant Sahani wrote:
> Hi Steved,
> I am sorry not for giving proper description . I have addressed your comments attached the patches .
> Thanks,
All three committed...
Next time please send the patches in separate emails and
in-line the patches instead of attaching them...
Thanks!
steved.
> Susant
>
>
> On 11/22/2013 09:58 PM, Steve Dickson wrote:
>> Hello,
>>
>> Would it be possible to get a little better description as
>> to what this patch does and why its needed...
>> "data race in bindresvport_sa" have very little
>> meaning, at least to me...
>>
>> More comments below...
>>
>> On 20/11/13 11:49, Susant Sahani wrote:
>>> Signed-off-by: Susant Sahani <ssahani@redhat.com>
>>> ---
>>> src/bindresvport.c | 16 +++++++++++++---
>>> 1 file changed, 13 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/src/bindresvport.c b/src/bindresvport.c
>>> index 6ce3e81..d26d754 100644
>>> --- a/src/bindresvport.c
>>> +++ b/src/bindresvport.c
>>> @@ -46,6 +46,7 @@
>>> #include <rpc/rpc.h>
>>> #include <string.h>
>>> +#include <reentrant.h>
>>> /*
>>> * Bind a socket to a privileged IP port
>>> @@ -79,17 +80,23 @@ bindresvport_sa(sd, sa)
>>> u_int16_t *portp;
>>> static u_int16_t port;
>>> static short startport = STARTPORT;
>>> + static pthread_mutex_t port_lock = PTHREAD_MUTEX_INITIALIZER;
>> How come you define this mutex statically instead in src/mt_misc.c
>> like the rest of the mutexes?
>>
>> Would you mind moving this (and the other two in the patches)
>> to src/mt_misc.c and added a commit talking about what they
>> are protecting
>>
>> tia!
>>
>> steved.
>>
>>> socklen_t salen;
>>> - int nports = ENDPORT - startport + 1;
>>> + int nports;
>>> int endport = ENDPORT;
>>> int i;
>>> + mutex_lock(&port_lock);
>>> + nports = ENDPORT - startport + 1;
>>> +
>>> if (sa == NULL) {
>>> salen = sizeof(myaddr);
>>> sa = (struct sockaddr *)&myaddr;
>>> - if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
>>> - return -1; /* errno is correctly set */
>>> + if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
>>> + mutex_unlock(&port_lock);
>>> + return -1; /* errno is correctly set */
>>> + }
>>> af = myaddr.ss_family;
>>> } else
>>> @@ -112,6 +119,7 @@ bindresvport_sa(sd, sa)
>>> #endif
>>> default:
>>> errno = EPFNOSUPPORT;
>>> + mutex_unlock(&port_lock);
>>> return (-1);
>>> }
>>> sa->sa_family = af;
>>> @@ -137,6 +145,8 @@ bindresvport_sa(sd, sa)
>>> port = LOWPORT + port % (STARTPORT - LOWPORT);
>>> goto again;
>>> }
>>> + mutex_unlock(&port_lock);
>>> +
>>> return (res);
>>> }
>>> #else
>>>
>
>
>
> ------------------------------------------------------------------------------
> Shape the Mobile Experience: Free Subscription
> Software experts and developers: Be at the forefront of tech innovation.
> Intel(R) Software Adrenaline delivers strategic insight and game-changing
> conversations that shape the rapidly evolving mobile landscape. Sign up now.
> http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk
>
>
>
> _______________________________________________
> Libtirpc-devel mailing list
> Libtirpc-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/libtirpc-devel
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-11-25 20:10 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-20 16:49 [PATCH 1/1] data race in bindresvport_sa Susant Sahani
2013-11-20 16:49 ` [PATCH] __nc_error() does not check return value from malloc Susant Sahani
2013-11-25 20:09 ` [Libtirpc-devel] " Steve Dickson
2013-11-20 16:49 ` [PATCH 1/1] race in clnt_vc_create Susant Sahani
2013-11-20 16:49 ` [PATCH 1/1] Race in getnetconfig Susant Sahani
2013-11-22 16:28 ` [PATCH 1/1] data race in bindresvport_sa Steve Dickson
2013-11-25 17:49 ` Susant Sahani
2013-11-25 20:11 ` [Libtirpc-devel] " Steve Dickson
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).