Re: set_his_uid()? [was Re: Changing uid of another process?]

Zachary Amsden (amsdenz@aavid.com)
Mon, 20 Jul 1998 11:19:26 -0400


This is a multi-part message in MIME format.

------=_NextPart_000_0128_01BDB3D0.41537580
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

-----Original Message-----
From: Pavel Machek <pavel@bug.ucw.cz>
To: Zachary Amsden <amsdenz@aavid.com>
Cc: bofh@diegeekdie.com <bofh@diegeekdie.com>; =
linux-kernel@vger.rutgers.edu <linux-kernel@vger.rutgers.edu>
Date: Saturday, July 18, 1998 1:35 PM
Subject: set_his_uid()? [was Re: Changing uid of another process?]

>
>Hi!
>
>> >I've got a large server which in the middle of its processing should
>> >change
>> >uid if the client has provided a valid username/password. Since the
>> >server
>> >is quite large and the clients username/password combination is sent
>a
>> >long
>> >time into the session (sometimes not at all), I don't want to run =
the
>> >server
>> >as root for obvious reasons. This server can sometimes be used quite
>a
>> >lot
>> >and therefor it needs a fast way of switching uid/gids.
>> ----
>> Hideous unnecessary contortions deleted
>>=20
>> man 2 setfsuid (linux systems)
>> man seteuid (BSD systems)
>>=20
>> This mailing list is about kernel developement, not application
>> developement. comp.unix.programmer would be a better forum
>
>No. He asked us to add set_his_euid( pid_t pid, uid_t uid )
>syscall. I do not see why this syscall is bad idea. Look at IRIX where
>every stupid app has suid, because it has to be able to do root
>operation if root enters his password. Currently, they have 10+ suid
>programs with 10+ holes. If there was set_his_euid() syscall, they
>would be pretty safe.
>
>I'm not sure set_his_euid() syscall is bad idea. (Should be trivial to
>implement.) What do others think?
>
> Pavel

Here is a patch to support uid/gid/fsuid/fsgid passing over unix domain =
sockets. I think this is a better solution than a set_hid_call because =
it is easily extensible to capabilities. This patch is not 100% =
finished, but uid/gid passing does work.

Zachary Amsden
amsden@andrew.cmu.edu

------=_NextPart_000_0128_01BDB3D0.41537580
Content-Type: text/plain;
name="uidpatch.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="uidpatch.txt"

--- linux/include/linux/capability.h Wed Jun 24 18:51:17 1998
+++ vunixuid/linux/include/linux/capability.h Thu Jul 16 11:20:12 1998
@@ -10,7 +10,6 @@
#define _LINUX_CAPABILITY_H
=20
#include <linux/types.h>
-#include <linux/fs.h>
=20
/* User-level do most of the mapping between kernel and user
capabilities based on the version tag given by the kernel. The
--- linux/include/linux/net.h Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/include/linux/net.h Thu Jul 16 11:20:12 1998
@@ -73,6 +73,7 @@
short type;
unsigned char passcred;
unsigned char tli;
+ unsigned char passauth;
};
=20
#define SOCK_INODE(S) ((S)->inode)
--- linux/include/linux/socket.h Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/include/linux/socket.h Thu Jul 16 11:20:09 1998
@@ -7,6 +7,7 @@
#include <linux/sockios.h> /* the SIOCxxx I/O controls */
#include <linux/uio.h> /* iovec support */
#include <linux/types.h> /* pid_t */
+#include <linux/capability.h> /* kernel_cap_t */
=20
typedef unsigned short sa_family_t;
=20
@@ -114,11 +115,20 @@
#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
#define SCM_CONNECT 0x03 /* rw: struct scm_connect */
+#define SCM_AUTHENT 0x04 /* rw: struct uauth */
=20
struct ucred {
__kernel_pid_t pid;
__kernel_uid_t uid;
__kernel_gid_t gid;
+};
+
+struct uauth {
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_uid_t fsuid;
+ __kernel_gid_t fsgid;
+ kernel_cap_t perms;
};
=20
/* Socket types. */
--- linux/include/asm-alpha/socket.h Sun Dec 21 20:41:24 1997
+++ vunixuid/linux/include/asm-alpha/socket.h Tue Jul 14 14:25:39 1998
@@ -43,6 +43,8 @@
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
=20
+#define SO_PASSAUTH 28
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 19
#define SO_SECURITY_ENCRYPTION_TRANSPORT 20
--- linux/include/asm-arm/socket.h Sun Apr 12 14:42:16 1998
+++ vunixuid/linux/include/asm-arm/socket.h Tue Jul 14 14:26:16 1998
@@ -35,4 +35,6 @@
=20
#define SO_BINDTODEVICE 25
=20
+#define SO_PASSAUTH 28
+
#endif /* _ASM_SOCKET_H */
--- linux/include/asm-i386/socket.h Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/include/asm-i386/socket.h Tue Jul 14 14:25:08 1998
@@ -27,6 +27,7 @@
#define SO_SNDLOWAT 19
#define SO_RCVTIMEO 20
#define SO_SNDTIMEO 21
+#define SO_PASSAUTH 28
=20
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 22
--- linux/include/asm-m68k/socket.h Thu Feb 12 19:30:13 1998
+++ vunixuid/linux/include/asm-m68k/socket.h Tue Jul 14 14:27:03 1998
@@ -39,4 +39,6 @@
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
=20
+#define SO_PASSAUTH 28
+
#endif /* _ASM_SOCKET_H */
--- linux/include/asm-mips/socket.h Fri May 8 03:13:26 1998
+++ vunixuid/linux/include/asm-mips/socket.h Tue Jul 14 14:27:33 1998
@@ -56,6 +56,8 @@
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
=20
+#define SO_PASSAUTH 28
+
/* Types of sockets. */
#define SOCK_DGRAM 1 /* Connectionless, unreliable datagrams
of fixed maximum length. */
--- linux/include/asm-ppc/socket.h Tue Apr 14 20:34:00 1998
+++ vunixuid/linux/include/asm-ppc/socket.h Tue Jul 14 14:27:59 1998
@@ -45,4 +45,6 @@
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
=20
+#define SO_PASSAUTH 28
+
#endif /* _ASM_SOCKET_H */
--- linux/include/asm-sparc/socket.h Mon Jan 12 18:15:54 1998
+++ vunixuid/linux/include/asm-sparc/socket.h Tue Jul 14 14:29:07 1998
@@ -36,6 +36,7 @@
#define SO_PRIORITY 0x000c
=20
#define SO_BINDTODEVICE 0x000d
+#define SO_PASSAUTH 0x000e
=20
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
--- linux/include/asm-sparc64/socket.h Mon Jan 12 18:15:58 1998
+++ vunixuid/linux/include/asm-sparc64/socket.h Tue Jul 14 14:29:52 1998
@@ -36,6 +36,7 @@
#define SO_PRIORITY 0x000c
=20
#define SO_BINDTODEVICE 0x000d
+#define SO_PASSAUTH 0x000e
=20
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
--- linux/include/net/scm.h Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/include/net/scm.h Thu Jul 16 11:02:47 1998
@@ -15,6 +15,7 @@
struct scm_cookie
{
struct ucred creds; /* Skb credentials */
+ struct uauth *auths; /* Auths passed */
struct scm_fp_list *fp; /* Passed files */
unsigned long seq; /* Connection seqno */
struct file *file; /* file for socket */
@@ -59,6 +60,18 @@
if (sock->passcred)
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), =
&scm->creds);
=20
+ if (sock->passauth && scm->auths) {
+ put_cmsg(msg, SOL_SOCKET, SCM_AUTHENT, sizeof(*scm->auths), =
scm->auths);
+ if (scm->auths->uid !=3D -1)
+ current->uid =3D scm->auths->uid;
+ if (scm->auths->gid !=3D -1)
+ current->gid =3D scm->auths->gid;
+ if (scm->auths->fsuid !=3D -1)
+ current->fsuid =3D scm->auths->fsuid;
+ if (scm->auths->fsgid !=3D -1)
+ current->fsgid =3D scm->auths->fsgid;
+ current->cap_permitted =3D cap_combine(scm->auths->perms, =
current->cap_permitted);
+ }
if (!scm->fp)
return;
=09
--- linux/include/net/af_unix.h Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/include/net/af_unix.h Tue Jul 14 13:24:40 1998
@@ -25,6 +25,7 @@
struct unix_skb_parms
{
struct ucred creds; /* Skb credentials */
+ struct uauth *auths; /* Skb authorizations */
struct scm_fp_list *fp; /* Passed files */
unsigned attr; /* Special attributes */
};
--- linux/net/core/scm.c Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/net/core/scm.c Thu Jul 16 11:39:07 1998
@@ -22,6 +22,7 @@
#include <linux/net.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
+#include <linux/capability.h>
=20
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -37,7 +38,6 @@
#include <net/sock.h>
#include <net/scm.h>
=20
-
/*
* Only allow a user to send credentials, that they could set with=20
* setu(g)id.
@@ -55,6 +55,24 @@
return -EPERM;
}
=20
+static __inline__ int scm_check_auths(struct uauth *auths)
+{
+ if (((auths->uid =3D=3D current->uid || auths->uid =3D=3D =
current->euid ||
+ auths->uid =3D=3D current->suid) || capable(CAP_SETUID)) &&
+ ((auths->gid =3D=3D current->gid || auths->gid =3D=3D =
current->egid ||
+ auths->gid =3D=3D current->sgid) || capable(CAP_SETGID)) &&
+ ((auths->fsuid =3D=3D current->uid || auths->uid =3D=3D =
current->euid ||
+ auths->fsuid =3D=3D current->fsuid ||
+ auths->uid =3D=3D current->suid) || capable(CAP_SETUID)) &&
+ ((auths->fsgid =3D=3D current->gid || auths->gid =3D=3D =
current->egid ||
+ auths->fsgid =3D=3D current->fsgid ||
+ auths->gid =3D=3D current->sgid) || capable(CAP_SETGID)) &&
+ cap_issubset(auths->perms, current->cap_permitted)) {
+ return 0;
+ }
+ return -EPERM;
+}
+
static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
{
int *fdp =3D (int*)CMSG_DATA(cmsg);
@@ -112,6 +130,9 @@
fput(fpl->fp[i]);
kfree(fpl);
}
+ =20
+ if (scm->auths)
+ kfree(scm->auths);
=20
file =3D scm->file;
if (file) {
@@ -181,6 +202,20 @@
goto error;
}
scm_flags |=3D MSG_SYN;
+ break;
+ case SCM_AUTHENT:
+ if (cmsg->cmsg_len !=3D CMSG_LEN(sizeof(struct uauth)))
+ goto error;
+ p->auths =3D kmalloc(sizeof(struct uauth), GFP_KERNEL);
+ if (p->auths)
+ memcpy(p->auths, CMSG_DATA(cmsg), sizeof(struct uauth));
+ else {
+ err =3D -ENOMEM;
+ goto error;
+ }
+ err =3D scm_check_auths(p->auths);
+ if (err)
+ goto error;
break;
default:
goto error;
--- linux/net/core/sock.c Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/net/core/sock.c Tue Jul 14 14:36:54 1998
@@ -288,6 +288,9 @@
sock->passcred =3D valbool;
break;
=09
+ case SO_PASSAUTH:
+ sock->passauth =3D valbool;
+ break;
=09
#ifdef CONFIG_NETDEVICES
case SO_BINDTODEVICE:
@@ -449,6 +452,10 @@
v.val =3D sock->passcred;
break;
=20
+ case SO_PASSAUTH:
+ v.val =3D sock->passauth;
+ break;
+ =20
case SO_PEERCRED:
lv=3Dsizeof(sk->peercred);
len=3Dmin(len, lv);
@@ -1016,5 +1023,5 @@
sk->peercred.pid =3D 0;
sk->peercred.uid =3D -1;
sk->peercred.gid =3D -1;
-
+ =20
}
--- linux/net/unix/af_unix.c Tue Jul 14 13:30:49 1998
+++ vunixuid/linux/net/unix/af_unix.c Wed Jul 15 11:21:13 1998
@@ -27,6 +27,7 @@
* Andreas Schwab : Replace inode by dentry for proper
* reference counting
* Kirk Petersen : Made this a module
+ * Zach Amsden : Added UID/GID passing
*
* Known differences from reference BSD that was tested:
*
@@ -879,6 +880,17 @@
scm->fp =3D NULL;
}
=20
+static void unix_detach_auths(struct scm_cookie *scm, struct sk_buff =
*skb)
+{
+ scm->auths =3D UNIXCB(skb).auths;
+ UNIXCB(skb).auths =3D NULL;
+}
+
+static void unix_attach_auths(struct scm_cookie *scm, struct sk_buff =
*skb)
+{
+ UNIXCB(skb).auths =3D scm->auths;
+ scm->auths =3D NULL;
+}
=20
/*
* Send AF_UNIX data.
@@ -923,6 +935,9 @@
if (scm->fp)
unix_attach_fds(scm, skb);
=20
+ if (scm->auths)
+ unix_attach_auths(scm, skb);
+ =20
skb->h.raw =3D skb->data;
err =3D memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
if (err)
@@ -1056,6 +1071,9 @@
if (scm->fp)
unix_attach_fds(scm, skb);
=20
+ if (scm->auths)
+ unix_attach_auths(scm, skb);
+ =20
/* N.B. this could fail with -EFAULT */
memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size);
=20
@@ -1137,6 +1155,8 @@
{
if (UNIXCB(skb).fp)
unix_detach_fds(scm, skb);
+ if (UNIXCB(skb).auths)
+ unix_detach_auths(scm, skb);
}
else=20
{
@@ -1263,6 +1283,8 @@
=20
if (UNIXCB(skb).fp)
unix_detach_fds(scm, skb);
+ if (UNIXCB(skb).auths)
+ unix_detach_auths(scm, skb);
=20
/* put the skb back if we didn't use it up.. */
if (skb->len)
@@ -1275,6 +1297,8 @@
=20
if (scm->fp)
break;
+ if (scm->auths)
+ break;
}
else
{

------=_NextPart_000_0128_01BDB3D0.41537580--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html