kern/102956: Add partial support for SO_PEERCRED in Linux emulation
Marcin Cieslak
saper at SYSTEM.PL
Wed Sep 6 23:50:21 UTC 2006
>Number: 102956
>Category: kern
>Synopsis: Add partial support for SO_PEERCRED in Linux emulation
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Sep 06 23:50:19 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Marcin Cieslak
>Release: FreeBSD 6.1-RC i386
>Organization:
System Business Consulting
>Environment:
System: FreeBSD saperski.saper.info 6.1-RC FreeBSD 6.1-RC #10: Fri Sep 1 02:20:15 CEST 2006 saper at saperski.saper.info:/usr/obj/usr/src/sys/VAIO i386
>Description:
Current Linux getsockopt() does not support SO_PEERCRED option used to fetch UNIX domain
socket peer PID, UID and GID.
Without this option ORACLE 10i Express Edition lsnrctl is unable to issue commands
to a running listener (including "status" and "stop").
All invocations result in the message:
TNS-01189: The listener could not authenticate the user
Linux lsnrctl using so called "OS Authentication" mode probes if UNIX socket
connection peer is the process run under to privileged "dba" group (or another group
listed in the DBA_GROUP parameter of the $ORACLE_HOME/network/admin/listener.ora file).
Security of this patch is not tested.
Known problem: Peer PID recognition is not done, we always return zero.
>How-To-Repeat:
Perform "${ORACLE_HOME}/bin/lsnrctl status" as the Oracle user.
>Fix:
Modified files:
$FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.59.2.1 2006/01/10 10:12:55 glebius Exp $
$FreeBSD: src/sys/i386/linux/linux.h,v 1.64 2005/04/13 04:31:43 mdodd Exp $
$FreeBSD: src/sys/amd64/linux32/linux.h,v 1.1 2004/08/16 07:55:06 tjr Exp $
$FreeBSD: src/sys/alpha/linux/linux.h,v 1.59 2004/08/16 07:05:44 tjr Exp $
--- /sys/i386/linux/linux.h.orig Wed Sep 6 20:36:43 2006
+++ /sys/i386/linux/linux.h Wed Sep 6 20:37:15 2006
@@ -615,6 +615,7 @@
#define LINUX_SO_NO_CHECK 11
#define LINUX_SO_PRIORITY 12
#define LINUX_SO_LINGER 13
+#define LINUX_SO_PEERCRED 17
#define LINUX_IP_TOS 1
#define LINUX_IP_TTL 2
--- /sys/alpha/linux/linux.h.orig Sun Oct 3 12:52:08 2004
+++ /sys/alpha/linux/linux.h Thu Sep 7 00:58:26 2006
@@ -447,6 +447,7 @@
#define LINUX_SO_NO_CHECK 11
#define LINUX_SO_PRIORITY 12
#define LINUX_SO_LINGER 13
+#define LINUX_SO_PEERCRED 17
#define LINUX_IP_TOS 1
#define LINUX_IP_TTL 2
--- /sys/amd64/linux32/linux.h.orig Mon Aug 16 09:55:06 2004
+++ /sys/amd64/linux32/linux.h Thu Sep 7 00:58:01 2006
@@ -635,6 +635,7 @@
#define LINUX_SO_NO_CHECK 11
#define LINUX_SO_PRIORITY 12
#define LINUX_SO_LINGER 13
+#define LINUX_SO_PEERCRED 17
#define LINUX_IP_TOS 1
#define LINUX_IP_TTL 2
--- /sys/compat/linux/linux_socket.c.orig Thu Sep 7 01:04:09 2006
+++ /sys/compat/linux/linux_socket.c Thu Sep 7 01:06:29 2006
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/compat/linux/linux_socket.c,v 1.59.2.1 2006/01/10 10:12:55 glebius Exp $");
+__FBSDID("$FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.59.2.1 2006/01/10 10:12:55 glebius Exp $");
/* XXX we use functions that might not exist. */
#include "opt_compat.h"
@@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/proc.h>
+#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/fcntl.h>
@@ -53,6 +54,7 @@
#include <sys/syscallsubr.h>
#include <sys/uio.h>
#include <sys/syslog.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -299,6 +301,8 @@
return (SO_OOBINLINE);
case LINUX_SO_LINGER:
return (SO_LINGER);
+ case LINUX_SO_PEERCRED:
+ return (LOCAL_PEERCRED);
}
return (-1);
}
@@ -1114,7 +1118,13 @@
caddr_t val;
int *avalsize;
} */ bsd_args;
- int error, name;
+ struct linux_ucred {
+ uint32_t pid;
+ uint32_t uid;
+ uint32_t gid;
+ } linux_ucred;
+ struct xucred xuc;
+ int error, name, optlen, rc, xuclen;
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
return (error);
@@ -1136,13 +1146,43 @@
name = -1;
break;
}
- if (name == -1)
+ if (name == -1) {
+ log(LOG_WARNING, "LINUX: 'getsockopt' level=0x%04x"
+ "optname=0x%04x not implemented\n",
+ linux_args.level, linux_args.optname);
return (EINVAL);
+ };
bsd_args.name = name;
- bsd_args.val = PTRIN(linux_args.optval);
- bsd_args.avalsize = PTRIN(linux_args.optlen);
- return (getsockopt(td, &bsd_args));
+ if (bsd_args.level == SOL_SOCKET && name == LOCAL_PEERCRED) {
+ if ((error = copyin(PTRIN(linux_args.optval),
+ &linux_ucred, sizeof(linux_ucred))))
+ return (error);
+ if ((error = copyin(PTRIN(linux_args.optlen),
+ &optlen, sizeof(optlen))))
+ return (error);
+ if (optlen < sizeof(linux_ucred))
+ return (EFAULT);
+ xuclen = sizeof(xuc);
+ if ((rc = error = kern_getsockopt(td, bsd_args.s,
+ 0, bsd_args.name,
+ (caddr_t) &xuc, UIO_SYSSPACE, &xuclen)))
+ return (error);
+ if (xuc.cr_version != XUCRED_VERSION)
+ return (EINVAL);
+ /* XXX get PID */
+ linux_ucred.pid = 0;
+ linux_ucred.uid = xuc.cr_uid;
+ linux_ucred.gid = xuc.cr_gid;
+ if ((error = copyout(&linux_ucred,
+ PTRIN(linux_args.optval), sizeof(linux_ucred))))
+ return (error);
+ return (rc);
+ } else {
+ bsd_args.val = PTRIN(linux_args.optval);
+ bsd_args.avalsize = PTRIN(linux_args.optlen);
+ return (getsockopt(td, &bsd_args));
+ };
}
int
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list