libuuid: avoid double open and leaking descriptor

We are opening /dev/urandom twice in uuid_generate(): first to check if
the file is available and then later __uuid_generate_random() again to
actually get the random data. Moreover, descriptor from the first open
is leaking.

Fix by passign the descriptor down the stack and reusing it there.

References: http://marc.info/?l=util-linux-ng&m=133406051131131&w=2

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
This commit is contained in:
Petr Uzel 2012-05-03 21:02:01 +02:00 committed by Karel Zak
parent 881a0f6b28
commit 6126f7a53c
6 changed files with 20 additions and 15 deletions

View File

@ -182,7 +182,7 @@ void create_doslabel(void)
unsigned int id;
/* random disk signature */
random_get_bytes(&id, sizeof(id));
random_get_bytes(&id, sizeof(id), -1);
fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id);

View File

@ -7,6 +7,6 @@
#endif
extern int random_get_fd(void);
extern void random_get_bytes(void *buf, size_t nbytes);
extern void random_get_bytes(void *buf, size_t nbytes, int fd);
#endif

View File

@ -58,13 +58,15 @@ int random_get_fd(void)
* Use /dev/urandom if possible, and if not,
* use glibc pseudo-random functions.
*/
void random_get_bytes(void *buf, size_t nbytes)
void random_get_bytes(void *buf, size_t nbytes, int fd)
{
size_t i, n = nbytes;
int fd = random_get_fd();
int lose_counter = 0;
unsigned char *cp = (unsigned char *) buf;
if (fd < 0)
fd = random_get_fd();
if (fd >= 0) {
while (n > 0) {
ssize_t x = read(fd, cp, n);
@ -111,7 +113,7 @@ int main(int argc, char *argv[])
/* generate and print 10 random numbers */
for (i = 0; i < 10; i++) {
random_get_bytes(&v, sizeof(v));
random_get_bytes(&v, sizeof(v), -1);
printf("%d\n", v);
}

View File

@ -277,7 +277,7 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
}
if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
random_get_bytes(&clock_seq, sizeof(clock_seq));
random_get_bytes(&clock_seq, sizeof(clock_seq), -1);
clock_seq &= 0x3FFF;
gettimeofday(&last, 0);
last.tv_sec--;
@ -434,7 +434,7 @@ int __uuid_generate_time(uuid_t out, int *num)
if (!has_init) {
if (get_node_id(node_id) <= 0) {
random_get_bytes(node_id, 6);
random_get_bytes(node_id, 6, -1);
/*
* Set multicast bit, to prevent conflicts
* with IEEE 802 addresses obtained from
@ -520,7 +520,7 @@ int uuid_generate_time_safe(uuid_t out)
}
void __uuid_generate_random(uuid_t out, int *num)
void __uuid_generate_random(uuid_t out, int *num, int fd)
{
uuid_t buf;
struct uuid uu;
@ -532,7 +532,7 @@ void __uuid_generate_random(uuid_t out, int *num)
n = *num;
for (i = 0; i < n; i++) {
random_get_bytes(buf, sizeof(buf));
random_get_bytes(buf, sizeof(buf), fd);
uuid_unpack(buf, &uu);
uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
@ -548,7 +548,7 @@ void uuid_generate_random(uuid_t out)
int num = 1;
/* No real reason to use the daemon for random uuid's -- yet */
__uuid_generate_random(out, &num);
__uuid_generate_random(out, &num, -1);
}
@ -560,8 +560,11 @@ void uuid_generate_random(uuid_t out)
*/
void uuid_generate(uuid_t out)
{
if (random_get_fd() >= 0)
uuid_generate_random(out);
int fd;
int num = 1;
if ((fd = random_get_fd()) >= 0)
__uuid_generate_random(out, &num, fd);
else
uuid_generate_time(out);
}

View File

@ -49,6 +49,6 @@
#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID
extern int __uuid_generate_time(uuid_t out, int *num);
extern void __uuid_generate_random(uuid_t out, int *num);
extern void __uuid_generate_random(uuid_t out, int *num, int fd);
#endif /* _UUID_UUID_H */

View File

@ -442,7 +442,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
break;
case UUIDD_OP_RANDOM_UUID:
num = 1;
__uuid_generate_random(uu, &num);
__uuid_generate_random(uu, &num, -1);
if (uuidd_cxt->debug) {
uuid_unparse(uu, str);
fprintf(stderr, _("Generated random UUID: %s\n"), str);
@ -473,7 +473,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
__uuid_generate_random((unsigned char *) reply_buf +
sizeof(num), &num);
sizeof(num), &num, -1);
if (uuidd_cxt->debug) {
fprintf(stderr, P_("Generated %d UUID:\n",
"Generated %d UUIDs:\n", num), num);