diff options
| author | NVSRahul <nvsrahul@hotmail.com> | 2026-01-13 05:52:06 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2026-03-07 07:51:16 +0000 |
| commit | 3570b19d74ed94dcc7fac2dcbf42b378bc72362e (patch) | |
| tree | 3fdab9bc6e9589a57f126e5b43d07012179eec11 | |
| parent | 16c82e28404ec959a7335ceae1d4f43881a50d9e (diff) | |
uuidgen: generate UUIDs in bounded batches to respect kernel limit
The uuidgen(2) system call enforces a hard upper limit of 2048 UUIDs per
invocation. uuidgen(1) previously attempted to generate arbitrary counts
in a single call and allocated memory accordingly, leading to EINVAL
errors, unnecessary memory usage, and potential overflow risks.
Generate UUIDs in fixed-size batches, streaming output incrementally
while preserving existing semantics. Mirror the kernel limit explicitly
since it is not exposed via a public interface.
Signed-off-by: NVSRahul <nvsrahul@hotmail.com>
Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1965
| -rw-r--r-- | bin/uuidgen/uuidgen.1 | 4 | ||||
| -rw-r--r-- | bin/uuidgen/uuidgen.c | 85 | ||||
| -rw-r--r-- | sys/kern/kern_uuid.c | 2 | ||||
| -rw-r--r-- | sys/sys/uuid.h | 6 |
4 files changed, 53 insertions, 44 deletions
diff --git a/bin/uuidgen/uuidgen.1 b/bin/uuidgen/uuidgen.1 index f7911b408f36..f88ea8d8631d 100644 --- a/bin/uuidgen/uuidgen.1 +++ b/bin/uuidgen/uuidgen.1 @@ -56,10 +56,6 @@ This option controls creation of compact UUID (without hyphen). .It Fl n This option controls the number of identifiers generated. By default, multiple identifiers are generated in batch. -The upper hard limit is 2048 -.Po see -.Xr uuidgen 2 -.Pc . .It Fl o Redirect output to .Ar filename diff --git a/bin/uuidgen/uuidgen.c b/bin/uuidgen/uuidgen.c index 3e2c0324a959..bcb7a45b665d 100644 --- a/bin/uuidgen/uuidgen.c +++ b/bin/uuidgen/uuidgen.c @@ -26,7 +26,9 @@ * */ +#include <sys/param.h> #include <sys/capsicum.h> +#include <sys/uuid.h> #include <capsicum_helpers.h> #include <err.h> @@ -156,46 +158,51 @@ main(int argc, char *argv[]) if (count == -1) count = 1; - store = (uuid_t *)malloc(sizeof(uuid_t) * count); - if (store == NULL) - err(1, "malloc()"); - - if (!iterate) { - /* Get them all in a single batch */ - if (version == 1) { - if (uuidgen(store, count) != 0) - err(1, "uuidgen()"); - } else if (version == 4) { - if (uuidgen_v4(store, count) != 0) - err(1, "uuidgen_v4()"); - } else { - err(1, "unsupported version"); - } - } else { - uuid = store; - for (i = 0; i < count; i++) { - if (version == 1) { - if (uuidgen(uuid++, 1) != 0) - err(1, "uuidgen()"); - } else if (version == 4) { - if (uuidgen_v4(uuid++, 1) != 0) - err(1, "uuidgen_v4()"); - } else { - err(1, "unsupported version"); - } - } - } - - uuid = store; - while (count--) { - tostring(uuid++, &p, &status); - if (status != uuid_s_ok) - err(1, "cannot stringify a UUID"); - fprintf(fp, "%s\n", p); - free(p); - } + store = calloc(MIN(count, UUIDGEN_BATCH_MAX), sizeof(uuid_t)); + if (store == NULL) + err(1, "calloc()"); + + while (count > 0) { + int batch = (count > UUIDGEN_BATCH_MAX) ? UUIDGEN_BATCH_MAX : count; + + if (!iterate) { + if (version == 1) { + if (uuidgen(store, batch) != 0) + err(1, "uuidgen()"); + } else if (version == 4) { + if (uuidgen_v4(store, batch) != 0) + err(1, "uuidgen_v4()"); + } else { + err(1, "unsupported version"); + } + } else { + uuid = store; + for (i = 0; i < batch; i++) { + if (version == 1) { + if (uuidgen(uuid++, 1) != 0) + err(1, "uuidgen()"); + } else if (version == 4) { + if (uuidgen_v4(uuid++, 1) != 0) + err(1, "uuidgen_v4()"); + } else { + err(1, "unsupported version"); + } + } + } + + uuid = store; + for (i = 0; i < batch; i++) { + tostring(uuid++, &p, &status); + if (status != uuid_s_ok) + err(1, "cannot stringify a UUID"); + fprintf(fp, "%s\n", p); + free(p); + } + + count -= batch; + } + free(store); - free(store); if (fp != stdout) fclose(fp); return (0); diff --git a/sys/kern/kern_uuid.c b/sys/kern/kern_uuid.c index fb27f7bbf736..136242ca2087 100644 --- a/sys/kern/kern_uuid.c +++ b/sys/kern/kern_uuid.c @@ -186,7 +186,7 @@ sys_uuidgen(struct thread *td, struct uuidgen_args *uap) * like to have some sort of upper-bound that's less than 2G :-) * XXX probably needs to be tunable. */ - if (uap->count < 1 || uap->count > 2048) + if (uap->count < 1 || uap->count > UUIDGEN_BATCH_MAX) return (EINVAL); count = uap->count; diff --git a/sys/sys/uuid.h b/sys/sys/uuid.h index 5fc5e61457de..3694988ccf5c 100644 --- a/sys/sys/uuid.h +++ b/sys/sys/uuid.h @@ -35,6 +35,12 @@ #define _UUID_NODE_LEN 6 /* + * The kernel imposes a limit on the number of UUIDs generated per call + * to avoid unbounded allocations. + */ +#define UUIDGEN_BATCH_MAX 2048 + +/* * See also: * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm |
