Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Sep 2006 01:43:21 +0200 (CEST)
From:      Marcin Cieslak <saper@SYSTEM.PL>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/102956: Add partial support for SO_PEERCRED in Linux emulation
Message-ID:  <200609062343.k86NhLhT004349@saperski.saper.info>
Resent-Message-ID: <200609062350.k86NoKCS050148@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609062343.k86NhLhT004349>