I know that there is not a shared maximum value for uid (or gid): some systems use 99 (Slackware, ...), others 65534 (Debian, ...).
I ask if there is a specific motivation to use 65534 and not 65535 (0xFFFF). Thank you.


If the max UID is 65535, then there is no value to indicate an error or unknown UID if the UID is stored in an unsigned 16-bit value.

  • So (uint16_t) -1 is used to indicate an error? – user1686 Jan 24 '14 at 13:21
  • @grawity At least it can be. Whether it actually is, well, not that I know of. But that's likely the thinking. – David Schwartz Jan 24 '14 at 19:09
  • When last I checked, (uid_t)-1 == cdrom – Joshua Nov 21 '16 at 16:21

Why 99?

This is not actually a maximum. It's a threshold, where the IDs for "system" accounts stop and the IDs for "real person" accounts start. It's fairly arbitrary and variable, too. There's no real reason for it to be 99 except that 100 is a handy round number.

It's a handy round number agreed upon by the various password and group database management tools for a platform. On Debian version 7, for example, the useradd and groupadd tools look in /etc/login.defs for the ranges of UIDs and GIDs that count as "system" and "user", and the latter range is 1000 to 60000 for both UIDs and GIDs.

Why 65534?

Firstly because there are two widespread conventions in POSIX system calls:

  • A return value of -1 (cast to the return type) indicates an error, with the error number available from the errno macro.
  • An input value of -1 indicates "don't change".

These aren't universal conventions. Notice that there's no possibility of an error return from the geteuid() system call, for example. (Processes always have effective UIDs.) So there's no static_cast<uid_t>(-1) to worry about there. But at least one of them applies to UIDs and GIDs. In the setreuid() and setregid() system calls an argument of -1 means "no change". So static_cast<uid_t>(-1) and static_cast<gid_t>(-1) aren't properly usable as actual IDs.

Secondly because UIDs and GIDs on Linux used to be 16-bit.

This changed to 32-bit around the turn of the century, but its echoes live on, and it is actually more subtle than it at first appears. -1 cast to a 16-bit unsigned integer, which is what uid_t and gid_t (at the system call interface) used to be, is of course 65535 as you observed. So this wasn't a usable UID or GID.

However, for the benefits of programs that used the 16-bit API on kernels that had switched to 32-bit uid_t and gid_t, Linux defined a "overflow UID" and an "overflow GID". This was because at various points there were some fairly nasty interactions due to the casting done between 16-bit and 32-bit. 16-bit programs saw UID 65536 as the superuser when the kernel didn't. Older kernels saw UID 131072 as the superuser when applications code didn't.

The "overflow UID" and "overflow GID" essentially mapped all 32-bit UIDs and GIDs greater than 65535 to 65534 for 16-bit code. This means that a second value, 0xFFFE, was now unusable as a real UID or GID value.

And, of course, -1 cast to the the 32-bit UID and GID type is also unusable.


Systems typically reserve the highest unsigned integer value 0xffff (or -1 if the value is interpreted as a signed integer) to indicate "invalid" or "unused".
(0xffff is 16-bit of course. Some systems use 32-bit 0xffffffff.)

Zero can not be used for that, because it is reserved for root use.
(Reserving 0 for root is, if i recall correctly, a POSIX convention that is observed by just about every other OS too, for compatibility reasons.)

  • 3
    User ID 0 is reserved for root, not the kernel. (Did you mean process ID 0?) – user1686 Jan 24 '14 at 13:25
  • OK, but I still don't understand the utility of this value: why should I create a new user with an 'invalid' (0xffff) uid? Or it's used to mean 'let it unchanged' when calling setreuid()? 'man setreuid' says that I have to put -1 as argument if I don't want uid or gid to change, but uid_t is unsigned. So I have to put 65535? – user2431763 Jan 24 '14 at 16:45
  • @grawity You are correct of course. I meant root. Too little sleep, I'm not running on all cylinders. Will edit the post. – Tonny Jan 24 '14 at 21:32
  • @user2431763 You will not put -1 there but the OS might do it. Example: Some Unix flavors set the UID of a deleted user to -1, but they don't actually remove the user from passwd. (This has the benefit that you can still look up information about the user, like full name, home-dir, what shell he/she used, later on.) It also prevents re-using the username, which often is forbidden by company policy. – Tonny Jan 24 '14 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.