isdn: fix information leak
Subsystems (3)
PATCH 1/1 isdn: fix information leak
The main motivation of this patch changing strcpy() to strlcpy(). We strcpy() to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls to strlcpy() prevent overflows.
drivers/isdn/sc/ioctl.c +5 -5
@@ -174,7 +174,7 @@ int sc_ioctl(int card, scs_ioctl *data)pr_debug ("%s: SCIOGETSPID: ioctl received\n" , sc_adapter[card]->devicename); - spid =kmalloc (SCIOC_SPIDSIZE ,GFP_KERNEL ); + spid =kzalloc (SCIOC_SPIDSIZE ,GFP_KERNEL );if (!spid) {kfree (rcvmsg);return -ENOMEM ;
@@ -194,7 +194,7 @@ int sc_ioctl(int card, scs_ioctl *data)kfree (rcvmsg);return status; } -strcpy (spid, rcvmsg->msg_data.byte_array); +strlcpy (spid, rcvmsg->msg_data.byte_array,SCIOC_SPIDSIZE );/* * Package the switch type and send to user space
@@ -272,12 +272,12 @@ int sc_ioctl(int card, scs_ioctl *data)return status; } - dn =kmalloc (SCIOC_DNSIZE ,GFP_KERNEL ); + dn =kzalloc (SCIOC_DNSIZE ,GFP_KERNEL );if (!dn) {kfree (rcvmsg);return -ENOMEM ; } -strcpy (dn, rcvmsg->msg_data.byte_array); +strlcpy (dn, rcvmsg->msg_data.byte_array,SCIOC_DNSIZE );kfree (rcvmsg);/*
@@ -348,7 +348,7 @@ int sc_ioctl(int card, scs_ioctl *data)pr_debug ("%s: SCIOSTAT: ioctl received\n" , sc_adapter[card]->devicename); - bi =kmalloc (sizeof (boardInfo),GFP_KERNEL ); + bi =kzalloc (sizeof (boardInfo),GFP_KERNEL );if (!bi) {kfree (rcvmsg);return -ENOMEM ;
Quoted 5 lines · Dan Carpenter
The main motivation of this patch changing
strcpy()tostrlcpy(). Westrcpy()to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls tostrlcpy()prevent overflows.
strlcpy() can handle the terminator NUL. so you don't need to zero it.
Quoted 49 lines
Signed-off-by Dan Carpenter <[email protected]>drivers/isdn/sc/ioctl.c +5
-5@@ -174,7 +174,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOGETSPID: ioctl received\n", sc_adapter[card]->devicename); - spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL); + spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL); if (!spid) { kfree(rcvmsg); return -ENOMEM;@@ -194,7 +194,7 @@ int sc_ioctl(int card, scs_ioctl *data) kfree(rcvmsg); return status; } - strcpy(spid, rcvmsg->msg_data.byte_array); + strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE); /** Package the switch type and send to user space @@ -272,12 +272,12 @@ int sc_ioctl(int card, scs_ioctl *data) return status; } - dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL); + dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL); if (!dn) { kfree(rcvmsg); return -ENOMEM; } - strcpy(dn, rcvmsg->msg_data.byte_array); + strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE); kfree(rcvmsg); /*@@ -348,7 +348,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOSTAT: ioctl received\n", sc_adapter[card]->devicename); - bi = kmalloc (sizeof(boardInfo), GFP_KERNEL); + bi = kzalloc(sizeof(boardInfo), GFP_KERNEL); if (!bi) { kfree(rcvmsg); return -ENOMEM;
Signature · 6 lines
Regards, Changli Gao([email protected]) -- To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 8 lines · Changli Gao
Quoted 5 lines · Dan Carpenter
The main motivation of this patch changing
strcpy()tostrlcpy(). Westrcpy()to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls tostrlcpy()prevent overflows.
strlcpy()can handle the terminator NUL. so you don't need to zero it.
If there are no NUL chars in "rcvmsg->msg_data.byte_array" then strlcpy() is sufficient, but if there is a NUL character then you need to zero the memory. The patch handles both possibilities.
regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 8 lines · Dan Carpenter
Quoted 7 lines · Changli Gao
Quoted 5 lines · Dan Carpenter
The main motivation of this patch changing
strcpy()tostrlcpy(). Westrcpy()to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls tostrlcpy()prevent overflows.
Quoted 6 lines
Quoted 1 line
strlcpy()can handle the terminator NUL. so you don't need to zero it.If there are no NUL chars in "
rcvmsg->msg_data.byte_array" thenstrlcpy()is sufficient, but if there is a NUL character then you need to zero the memory. The patch handles both possibilities.
the second parameter of strlcpy() must a NUL terminated C string. I think you means strncpy().
FYI:
http://lxr.linux.no/#linux+v2.6.35/lib/string.c#L146
http://lxr.linux.no/#linux+v2.6.35/lib/string.c#L119
Signature · 6 lines
Regards, Changli Gao([email protected]) -- To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 4 lines · Changli Gao
the second parameter of
strlcpy()must a NUL terminated C string. I think you meansstrncpy().
Both strncpy() and strlcpy() take a limitter. The difference is that strlcpy() always takes on a terminator and strncpy() only adds a terminator if there is space.
strlcpy() is a BSD function that never caught on in Linux. The glibc maintainers think that if you accidentally chop off the last part of a word that makes you an idiot. They think you should known the length of your data at all times and use memcpy() or a proper string library.
I prefer strlcpy() to strncpy(). Some people do stuff like:
strncpy(bar, foo, n); bar[n] = '\0';
You have to read through the code to find if n is "sizeof(bar)" or "sizeof(bar) - 1". Which is a pain in the arse. strlcpy() is explicit and it's just one line of code instead of two.
The other tricky thing you should remember about strncpy() is that the posix version writes NUL chars from the end of the string to the limitter but the kernel version only copies one NUL character.
regards,
dan carpenter
Quoted 17 lines · Dan Carpenter
Both
strncpy()andstrlcpy()take a limitter. The difference is thatstrlcpy()always takes on a terminator andstrncpy()only adds a terminator if there is space.
strlcpy()is a BSD function that never caught on in Linux. The glibc maintainers think that if you accidentally chop off the last part of a word that makes you an idiot. They think you should known the length of your data at all times and usememcpy()or a proper string library.I prefer
strlcpy()tostrncpy(). Some people do stuff like:
strncpy(bar, foo, n);
bar[n] = '\0';
You have to read through the code to find if n is "sizeof(bar)" or "sizeof(bar) - 1". Which is a pain in the arse. strlcpy() is explicit and it's just one line of code instead of two.
Quoted 4 lines
The other tricky thing you should remember about
strncpy()is that the posix version writes NUL chars from the end of the string to the limitter but the kernel version only copies one NUL character.
You should spend some time on reading the source code of strlcpy() and strncpy().
the example use of them is:
char dst[24];
char *src = "test";
strncpy(dst, src, sizeof(dst) - 1);strlcpy(dst, src, sizeof(dst));
both of them don't need to zero dst, and they don't need to pad zero at then end of the dst.
Signature · 6 lines
Regards, Changli Gao([email protected]) -- To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 26 lines · Changli Gao
Quoted 17 lines · Dan Carpenter
Both
strncpy()andstrlcpy()take a limitter. The difference is thatstrlcpy()always takes on a terminator andstrncpy()only adds a terminator if there is space.
strlcpy()is a BSD function that never caught on in Linux. The glibc maintainers think that if you accidentally chop off the last part of a word that makes you an idiot. They think you should known the length of your data at all times and usememcpy()or a proper string library.I prefer
strlcpy()tostrncpy(). Some people do stuff like:
strncpy(bar, foo, n);
bar[n] = '\0';
You have to read through the code to find if n is "sizeof(bar)" or "sizeof(bar) - 1". Which is a pain in the arse. strlcpy() is explicit and it's just one line of code instead of two.Quoted 4 lines
The other tricky thing you should remember about
strncpy()is that the posix version writes NUL chars from the end of the string to the limitter but the kernel version only copies one NUL character.You should spend some time on reading the source code of
strlcpy()andstrncpy().
Quoted 6 lines
the example use of them is:
char dst[24];
char *src = "test";
strncpy(dst, src, sizeof(dst) - 1);
Oh, Sorry, I made a mistake here. As you said, the code should be
strncpy(dst, src, sizeof(dst));
dst[sizeof(dst) - 1] = '\0';
However, if you use strlcpy(), you really don't need to zero the dst buffer.
Quoted 5 lines
strlcpy(dst, src, sizeof(dst));both of them don't need to zero dst, and they don't need to pad zero at then end of the dst.
Signature · 6 lines
Regards, Changli Gao([email protected]) -- To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
First of all, I'm happy that you're reviewing these patches. A lot of learner, often untested, patches go through kernel-janitors and the entire purpose of the list is to check each other's work.
Here is what I meant by an information leak. The original code did:
spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
...
strcpy(spid, rcvmsg->msg_data.byte_array);
...
if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {When you allocate memory with kmalloc() it doesn't clear that memory. It could have anything in there including passwords etc. If there is a short string in "rcvmsg->msg_data.byte_array" like "123" then the strcpy() puts that in the first 4 bytes of "spid", but the rest of the buffer is still full of passwords.
The copy_to_user() sends it to the user, and normally the user only reads as far as the terminator, but if they read past that then they would see all the passwords etc that were saved there.
This function is in the ioctl() probably only root has open() permission on the device so it's not a big deal because root can already find your password. But I didn't dig that far. It's just simpler to zero out the memory instead of worrying about if it really is exploitable or not.
Also it's quite possible that the strcpy can't overflow. But it's weird for the code to leave space for the terminator and then not use it. In the end, I decided to do the cautious thing and be done with it.
regards,
dan carpenter
Quoted 21 lines · Dan Carpenter
First of all, I'm happy that you're reviewing these patches. A lot of learner, often untested, patches go through kernel-janitors and the entire purpose of the list is to check each other's work.
Here is what I meant by an information leak. The original code did:
spid =kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
...
strcpy(spid,rcvmsg->msg_data.byte_array);
...
if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {When you allocate memory with
kmalloc()it doesn't clear that memory. It could have anything in there including passwords etc. If there is a short string in "rcvmsg->msg_data.byte_array" like "123" then thestrcpy()puts that in the first 4 bytes of "spid", but the rest of the buffer is still full of passwords.The
copy_to_user()sends it to the user, and normally the user only reads as far as the terminator, but if they read past that then they would see all the passwords etc that were saved there.
Quoted 9 lines
This function is in the
ioctl()probably only root hasopen()permission on the device so it's not a big deal because root can already find your password. But I didn't dig that far. It's just simpler to zero out the memory instead of worrying about if it really is exploitable or not.Also it's quite possible that the strcpy can't overflow. But it's weird for the code to leave space for the terminator and then not use it. In the end, I decided to do the cautious thing and be done with it.
Thanks, Dan. I got it.
Signature · 6 lines
Regards, Changli Gao([email protected]) -- To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Dan Carpenter <[email protected]>
Date: Thu, 5 Aug 2010 11:38:06 +0200
Quoted 7 lines
The main motivation of this patch changing
strcpy()tostrlcpy(). Westrcpy()to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls tostrlcpy()prevent overflows.Signed-off-by Dan Carpenter <[email protected]>
Applied.