Merge remote branch 'rjy/clientids'
This commit is contained in:
		
						commit
						8e4c3ce55b
					
				|  | @ -40,6 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||||
| #include "propertyst.h" | #include "propertyst.h" | ||||||
| #include "extnsionst.h" | #include "extnsionst.h" | ||||||
| #include "xacestr.h" | #include "xacestr.h" | ||||||
|  | #include "client.h" | ||||||
| #include "../os/osdep.h" | #include "../os/osdep.h" | ||||||
| #define _XSELINUX_NEED_FLASK_MAP | #define _XSELINUX_NEED_FLASK_MAP | ||||||
| #include "xselinuxint.h" | #include "xselinuxint.h" | ||||||
|  | @ -129,26 +130,25 @@ SELinuxLabelClient(ClientPtr client) | ||||||
| 
 | 
 | ||||||
|     /* For local clients, try and determine the executable name */ |     /* For local clients, try and determine the executable name */ | ||||||
|     if (XaceIsLocal(client)) { |     if (XaceIsLocal(client)) { | ||||||
| 	struct ucred creds; | 	/* Get cached command name if CLIENTIDS is enabled. */ | ||||||
| 	socklen_t len = sizeof(creds); | 	const char *cmdname = GetClientCmdName(client); | ||||||
| 	char path[PATH_MAX + 1]; | 	Bool cached = (cmdname != NULL); | ||||||
| 	size_t bytes; | 	/* If CLIENTIDS is disabled, figure out the command name from
 | ||||||
|  | 	 * scratch. */ | ||||||
|  | 	if (!cmdname) | ||||||
|  | 	{ | ||||||
|  | 	    pid_t pid = DetermineClientPid(client); | ||||||
|  | 	    if (pid != -1) | ||||||
|  | 		DetermineClientCmd(pid, &cmdname, NULL); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	memset(&creds, 0, sizeof(creds)); | 	if (!cmdname) | ||||||
| 	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0) |  | ||||||
| 	    goto finish; | 	    goto finish; | ||||||
| 
 | 
 | ||||||
| 	snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid); | 	strncpy(subj->command, cmdname, COMMAND_LEN - 1); | ||||||
| 	fd = open(path, O_RDONLY); |  | ||||||
| 	if (fd < 0) |  | ||||||
| 	    goto finish; |  | ||||||
| 
 | 
 | ||||||
| 	bytes = read(fd, path, PATH_MAX + 1); | 	if (!cached) | ||||||
| 	close(fd); | 	    free((void *) cmdname); /* const char * */ | ||||||
| 	if (bytes <= 0) |  | ||||||
| 	    goto finish; |  | ||||||
| 
 |  | ||||||
| 	strncpy(subj->command, path, COMMAND_LEN - 1); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| finish: | finish: | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								configure.ac
								
								
								
								
							
							
						
						
									
										28
									
								
								configure.ac
								
								
								
								
							|  | @ -312,19 +312,6 @@ AC_CHECK_HEADER([execinfo.h],[ | ||||||
|     ])] |     ])] | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| dnl ARM needs additional compiler flags for proper backtraces if GCC is |  | ||||||
| dnl used. Compile a dummy program with the -mapcs-frame option. If it |  | ||||||
| dnl succeeds, we know that we are building for ARM with GCC. |  | ||||||
| old_CFLAGS="$CFLAGS" |  | ||||||
| CFLAGS="-mapcs-frame" |  | ||||||
| AC_COMPILE_IFELSE( |  | ||||||
|         AC_LANG_PROGRAM([[ ]]), |  | ||||||
|         ARM_BACKTRACE_CFLAGS="$CFLAGS", |  | ||||||
|         ARM_BACKTRACE_CFLAGS="" |  | ||||||
| ) |  | ||||||
| CFLAGS="$old_CFLAGS" |  | ||||||
| AC_SUBST(ARM_BACKTRACE_CFLAGS) |  | ||||||
| 
 |  | ||||||
| dnl --------------------------------------------------------------------------- | dnl --------------------------------------------------------------------------- | ||||||
| dnl Bus options and CPU capabilities.  Replaces logic in | dnl Bus options and CPU capabilities.  Replaces logic in | ||||||
| dnl hw/xfree86/os-support/bus/Makefile.am, among others. | dnl hw/xfree86/os-support/bus/Makefile.am, among others. | ||||||
|  | @ -641,6 +628,7 @@ AC_ARG_ENABLE(vbe,            AS_HELP_STRING([--enable-vbe], [Build Xorg with VB | ||||||
| AC_ARG_ENABLE(int10-module,     AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) | AC_ARG_ENABLE(int10-module,     AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) | ||||||
| AC_ARG_ENABLE(windowswm,      AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) | AC_ARG_ENABLE(windowswm,      AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) | ||||||
| AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) | AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) | ||||||
|  | AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) | ||||||
| 
 | 
 | ||||||
| dnl DDXes. | dnl DDXes. | ||||||
| AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) | AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) | ||||||
|  | @ -994,6 +982,18 @@ if test "x$RES" = xyes; then | ||||||
| 	REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" | 	REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
|  | # The XRes extension may support client ID tracking only if it has | ||||||
|  | # been specifically enabled. Client ID tracking is implicitly not | ||||||
|  | # supported if XRes extension is disabled. | ||||||
|  | AC_MSG_CHECKING([whether to track client ids]) | ||||||
|  | if test "x$RES" = xyes && test "x$CLIENTIDS" = xyes; then | ||||||
|  | 	AC_DEFINE(CLIENTIDS, 1, [Support client ID tracking]) | ||||||
|  | else | ||||||
|  | 	CLIENTIDS=no | ||||||
|  | fi | ||||||
|  | AC_MSG_RESULT([$CLIENTIDS]) | ||||||
|  | AM_CONDITIONAL(CLIENTIDS, [test "x$CLIENTIDS" = xyes]) | ||||||
|  | 
 | ||||||
| if test "x$GLX" = xyes; then | if test "x$GLX" = xyes; then | ||||||
| 	PKG_CHECK_MODULES([XLIB], [x11]) | 	PKG_CHECK_MODULES([XLIB], [x11]) | ||||||
| 	PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) | 	PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) | ||||||
|  | @ -1525,7 +1525,7 @@ if test "x$XNEST" = xyes; then | ||||||
| 	if test "x$have_xnest" = xno; then | 	if test "x$have_xnest" = xno; then | ||||||
| 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) | 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) | ||||||
| 	fi | 	fi | ||||||
| 	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB" | 	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" | ||||||
| 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" | 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" | ||||||
| 	AC_SUBST([XNEST_LIBS]) | 	AC_SUBST([XNEST_LIBS]) | ||||||
| 	AC_SUBST([XNEST_SYS_LIBS]) | 	AC_SUBST([XNEST_SYS_LIBS]) | ||||||
|  |  | ||||||
|  | @ -130,6 +130,7 @@ int ProcInitialConnection(); | ||||||
| #include "inputstr.h" | #include "inputstr.h" | ||||||
| #include "xkbsrv.h" | #include "xkbsrv.h" | ||||||
| #include "site.h" | #include "site.h" | ||||||
|  | #include "client.h" | ||||||
| 
 | 
 | ||||||
| #ifdef XSERVER_DTRACE | #ifdef XSERVER_DTRACE | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
|  | @ -3459,6 +3460,9 @@ CloseDownClient(ClientPtr client) | ||||||
| 	    CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); | 	    CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); | ||||||
| 	} 	     | 	} 	     | ||||||
| 	FreeClientResources(client); | 	FreeClientResources(client); | ||||||
|  | 	/* Disable client ID tracking. This must be done after
 | ||||||
|  | 	 * ClientStateCallback. */ | ||||||
|  | 	ReleaseClientIds(client); | ||||||
| #ifdef XSERVER_DTRACE | #ifdef XSERVER_DTRACE | ||||||
| 	XSERVER_CLIENT_DISCONNECT(client->index); | 	XSERVER_CLIENT_DISCONNECT(client->index); | ||||||
| #endif	 | #endif	 | ||||||
|  | @ -3496,6 +3500,7 @@ void InitClient(ClientPtr client, int i, pointer ospriv) | ||||||
|     client->smart_start_tick = SmartScheduleTime; |     client->smart_start_tick = SmartScheduleTime; | ||||||
|     client->smart_stop_tick = SmartScheduleTime; |     client->smart_stop_tick = SmartScheduleTime; | ||||||
|     client->smart_check_tick = SmartScheduleTime; |     client->smart_check_tick = SmartScheduleTime; | ||||||
|  |     client->clientIds = NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /************************
 | /************************
 | ||||||
|  | @ -3535,6 +3540,11 @@ ClientPtr NextAvailableClient(pointer ospriv) | ||||||
| 	currentMaxClients++; | 	currentMaxClients++; | ||||||
|     while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) |     while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) | ||||||
| 	nextFreeClientID++; | 	nextFreeClientID++; | ||||||
|  | 
 | ||||||
|  |     /* Enable client ID tracking. This must be done before
 | ||||||
|  |      * ClientStateCallback. */ | ||||||
|  |     ReserveClientIds(client); | ||||||
|  | 
 | ||||||
|     if (ClientStateCallback) |     if (ClientStateCallback) | ||||||
|     { |     { | ||||||
| 	NewClientInfoRec clientinfo; | 	NewClientInfoRec clientinfo; | ||||||
|  |  | ||||||
|  | @ -104,6 +104,7 @@ Equipment Corporation. | ||||||
| #include "extnsionst.h" | #include "extnsionst.h" | ||||||
| #include "privates.h" | #include "privates.h" | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
|  | #include "client.h" | ||||||
| #ifdef PANORAMIX | #ifdef PANORAMIX | ||||||
| #include "panoramiXsrv.h" | #include "panoramiXsrv.h" | ||||||
| #else | #else | ||||||
|  | @ -258,6 +259,7 @@ int main(int argc, char *argv[], char *envp[]) | ||||||
|         InitCoreDevices(); |         InitCoreDevices(); | ||||||
| 	InitInput(argc, argv); | 	InitInput(argc, argv); | ||||||
| 	InitAndStartDevices(); | 	InitAndStartDevices(); | ||||||
|  | 	ReserveClientIds(serverClient); | ||||||
| 
 | 
 | ||||||
| 	dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); | 	dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); | ||||||
| 
 | 
 | ||||||
|  | @ -323,6 +325,7 @@ int main(int argc, char *argv[], char *envp[]) | ||||||
| 	    screenInfo.numScreens = i; | 	    screenInfo.numScreens = i; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	ReleaseClientIds(serverClient); | ||||||
| 	dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); | 	dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); | ||||||
| 	serverClient->devPrivates = NULL; | 	serverClient->devPrivates = NULL; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -259,6 +259,7 @@ cat > sdksyms.c << EOF | ||||||
| #include "colormap.h" | #include "colormap.h" | ||||||
| #include "colormapst.h" | #include "colormapst.h" | ||||||
| #include "hotplug.h" | #include "hotplug.h" | ||||||
|  | #include "client.h" | ||||||
| #include "cursor.h" | #include "cursor.h" | ||||||
| #include "cursorstr.h" | #include "cursorstr.h" | ||||||
| #include "dix.h" | #include "dix.h" | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ sdk_HEADERS =		\ | ||||||
| 	XIstubs.h	\
 | 	XIstubs.h	\
 | ||||||
| 	Xprintf.h	\
 | 	Xprintf.h	\
 | ||||||
| 	callback.h	\
 | 	callback.h	\
 | ||||||
|  | 	client.h	\
 | ||||||
| 	closestr.h	\
 | 	closestr.h	\
 | ||||||
| 	closure.h	\
 | 	closure.h	\
 | ||||||
| 	colormap.h	\
 | 	colormap.h	\
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All | ||||||
|  |  * rights reserved. | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* Author: Rami Ylimäki <rami.ylimaki@vincit.fi> */ | ||||||
|  | 
 | ||||||
|  | #ifndef CLIENT_H | ||||||
|  | #define CLIENT_H | ||||||
|  | 
 | ||||||
|  | #ifdef HAVE_DIX_CONFIG_H | ||||||
|  | #include <dix-config.h> | ||||||
|  | #endif /* HAVE_DIX_CONFIG_H */ | ||||||
|  | #include <X11/Xfuncproto.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | 
 | ||||||
|  | /* Client IDs. Use GetClientPid, GetClientCmdName and GetClientCmdArgs
 | ||||||
|  |  * instead of accessing the fields directly. */ | ||||||
|  | typedef struct { | ||||||
|  |     pid_t pid;           /* process ID, -1 if not available */ | ||||||
|  |     const char *cmdname; /* process name, NULL if not available */ | ||||||
|  |     const char *cmdargs; /* process arguments, NULL if not available */ | ||||||
|  | } ClientIdRec, *ClientIdPtr; | ||||||
|  | 
 | ||||||
|  | struct _Client; | ||||||
|  | 
 | ||||||
|  | /* Initialize and clean up. */ | ||||||
|  | void ReserveClientIds(struct _Client *client); | ||||||
|  | void ReleaseClientIds(struct _Client *client); | ||||||
|  | 
 | ||||||
|  | /* Determine client IDs for caching. Exported on purpose for
 | ||||||
|  |  * extensions such as SELinux. */ | ||||||
|  | extern _X_EXPORT pid_t DetermineClientPid(struct _Client *client); | ||||||
|  | extern _X_EXPORT void DetermineClientCmd(pid_t, const char **cmdname, const char **cmdargs); | ||||||
|  | 
 | ||||||
|  | /* Query cached client IDs. Exported on purpose for drivers. */ | ||||||
|  | extern _X_EXPORT pid_t GetClientPid(struct _Client *client); | ||||||
|  | extern _X_EXPORT const char *GetClientCmdName(struct _Client *client); | ||||||
|  | extern _X_EXPORT const char *GetClientCmdArgs(struct _Client *client); | ||||||
|  | 
 | ||||||
|  | #endif /* CLIENT_H */ | ||||||
|  | @ -279,6 +279,9 @@ | ||||||
| /* Support X resource extension */ | /* Support X resource extension */ | ||||||
| #undef RES | #undef RES | ||||||
| 
 | 
 | ||||||
|  | /* Support client ID tracking in X resource extension */ | ||||||
|  | #undef CLIENTIDS | ||||||
|  | 
 | ||||||
| /* Support MIT-SCREEN-SAVER extension */ | /* Support MIT-SCREEN-SAVER extension */ | ||||||
| #undef SCREENSAVER | #undef SCREENSAVER | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ SOFTWARE. | ||||||
| #ifndef DIXSTRUCT_H | #ifndef DIXSTRUCT_H | ||||||
| #define DIXSTRUCT_H | #define DIXSTRUCT_H | ||||||
| 
 | 
 | ||||||
|  | #include "client.h" | ||||||
| #include "dix.h" | #include "dix.h" | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
| #include "cursor.h" | #include "cursor.h" | ||||||
|  | @ -121,6 +122,7 @@ typedef struct _Client { | ||||||
|     long    smart_check_tick; |     long    smart_check_tick; | ||||||
|      |      | ||||||
|     DeviceIntPtr clientPtr; |     DeviceIntPtr clientPtr; | ||||||
|  |     ClientIdPtr  clientIds; | ||||||
| }           ClientRec; | }           ClientRec; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -1,25 +1,18 @@ | ||||||
| noinst_LTLIBRARIES = libos.la liblog.la | noinst_LTLIBRARIES = libos.la | ||||||
| 
 | 
 | ||||||
| AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) | AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) | ||||||
| 
 | 
 | ||||||
| SECURERPC_SRCS = rpcauth.c | SECURERPC_SRCS = rpcauth.c | ||||||
| XDMCP_SRCS = xdmcp.c | XDMCP_SRCS = xdmcp.c | ||||||
| STRLCAT_SRCS = strlcat.c strlcpy.c | STRLCAT_SRCS = strlcat.c strlcpy.c | ||||||
| 
 | XORG_SRCS = log.c | ||||||
| # Build a convenience library liblog.la that will be added into
 |  | ||||||
| # libos.la. The split is done so that log.c can be built with
 |  | ||||||
| # different compiler options.
 |  | ||||||
| liblog_la_SOURCES = log.c |  | ||||||
| # Add flags needed for proper backtraces of functions marked with GCC
 |  | ||||||
| # __attribute__((noreturn)). Currently those flags are needed for
 |  | ||||||
| # FatalError and AbortServer in log.c.
 |  | ||||||
| liblog_la_CFLAGS = $(AM_CFLAGS) $(ARM_BACKTRACE_CFLAGS) |  | ||||||
| 
 | 
 | ||||||
| libos_la_SOURCES = 	\
 | libos_la_SOURCES = 	\
 | ||||||
| 	WaitFor.c	\
 | 	WaitFor.c	\
 | ||||||
| 	access.c	\
 | 	access.c	\
 | ||||||
| 	auth.c		\
 | 	auth.c		\
 | ||||||
| 	backtrace.c	\
 | 	backtrace.c	\
 | ||||||
|  | 	client.c	\
 | ||||||
| 	connection.c	\
 | 	connection.c	\
 | ||||||
| 	io.c		\
 | 	io.c		\
 | ||||||
| 	mitauth.c	\
 | 	mitauth.c	\
 | ||||||
|  | @ -32,8 +25,9 @@ libos_la_SOURCES = 	\ | ||||||
| 	xdmauth.c	\
 | 	xdmauth.c	\
 | ||||||
| 	xsha1.c		\
 | 	xsha1.c		\
 | ||||||
| 	xstrans.c	\
 | 	xstrans.c	\
 | ||||||
| 	xprintf.c | 	xprintf.c	\
 | ||||||
| libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) liblog.la | 	$(XORG_SRCS) | ||||||
|  | libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) | ||||||
| 
 | 
 | ||||||
| if SECURE_RPC | if SECURE_RPC | ||||||
| libos_la_SOURCES += $(SECURERPC_SRCS) | libos_la_SOURCES += $(SECURERPC_SRCS) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,310 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All | ||||||
|  |  * rights reserved. | ||||||
|  |  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @file | ||||||
|  |  * | ||||||
|  |  * This file contains functionality for identifying clients by various | ||||||
|  |  * means. The primary purpose of identification is to simply aid in | ||||||
|  |  * finding out which clients are using X server and how they are using | ||||||
|  |  * it. For example, it's often necessary to monitor what requests | ||||||
|  |  * clients are executing (to spot bad behaviour) and how they are | ||||||
|  |  * allocating resources in X server (to spot excessive resource | ||||||
|  |  * usage). | ||||||
|  |  * | ||||||
|  |  * This framework automatically allocates information, that can be | ||||||
|  |  * used for client identification, when a client connects to the | ||||||
|  |  * server. The information is freed when the client disconnects. The | ||||||
|  |  * allocated information is just a collection of various IDs, such as | ||||||
|  |  * PID and process name for local clients, that are likely to be | ||||||
|  |  * useful in analyzing X server usage. | ||||||
|  |  * | ||||||
|  |  * Users of the framework can query ID information about clients at | ||||||
|  |  * any time. To avoid repeated polling of IDs the users can also | ||||||
|  |  * subscribe for notifications about the availability of ID | ||||||
|  |  * information. IDs have been allocated before ClientStateCallback is | ||||||
|  |  * called with ClientStateInitial state. Similarly the IDs will be | ||||||
|  |  * released after ClientStateCallback is called with ClientStateGone | ||||||
|  |  * state. | ||||||
|  |  * | ||||||
|  |  * Author: Rami Ylimäki <rami.ylimaki@vincit.fi> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "client.h" | ||||||
|  | #include "os.h" | ||||||
|  | #include "dixstruct.h" | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Try to determine a PID for a client from its connection | ||||||
|  |  * information. This should be called only once when new client has | ||||||
|  |  * connected, use GetClientPid to determine the PID at other times. | ||||||
|  |  * | ||||||
|  |  * @param[in] client Connection linked to some process. | ||||||
|  |  * | ||||||
|  |  * @return PID of the client. Error (-1) if PID can't be determined | ||||||
|  |  *         for the client. | ||||||
|  |  * | ||||||
|  |  * @see GetClientPid | ||||||
|  |  */ | ||||||
|  | pid_t DetermineClientPid(struct _Client *client) | ||||||
|  | { | ||||||
|  |     LocalClientCredRec *lcc = NULL; | ||||||
|  |     pid_t pid = -1; | ||||||
|  | 
 | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return pid; | ||||||
|  | 
 | ||||||
|  |     if (client == serverClient) | ||||||
|  |         return getpid(); | ||||||
|  | 
 | ||||||
|  |     if (GetLocalClientCreds(client, &lcc) != -1) | ||||||
|  |     { | ||||||
|  |         if (lcc->fieldsSet & LCC_PID_SET) | ||||||
|  |             pid = lcc->pid; | ||||||
|  |         FreeLocalClientCreds(lcc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return pid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Try to determine a command line string for a client based on its | ||||||
|  |  * PID. Note that mapping PID to a command hasn't been implemented for | ||||||
|  |  * some operating systems. This should be called only once when a new | ||||||
|  |  * client has connected, use GetClientCmdName/Args to determine the | ||||||
|  |  * string at other times. | ||||||
|  |  * | ||||||
|  |  * @param[in]  pid     Process ID of a client. | ||||||
|  | 
 | ||||||
|  |  * @param[out] cmdname Client process name without arguments. You must | ||||||
|  |  *                     release this by calling free. On error NULL is | ||||||
|  |  *                     returned. Pass NULL if you aren't interested in | ||||||
|  |  *                     this value. | ||||||
|  |  * @param[out] cmdargs Arguments to client process. Useful for | ||||||
|  |  *                     identifying a client that is executed from a | ||||||
|  |  *                     launcher program. You must release this by | ||||||
|  |  *                     calling free. On error NULL is returned. Pass | ||||||
|  |  *                     NULL if you aren't interested in this value. | ||||||
|  |  * | ||||||
|  |  * @see GetClientCmdName/Args | ||||||
|  |  */ | ||||||
|  | void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) | ||||||
|  | { | ||||||
|  |     char path[PATH_MAX + 1]; | ||||||
|  |     int totsize = 0; | ||||||
|  |     int cmdsize = 0; | ||||||
|  |     int argsize = 0; | ||||||
|  |     int fd = 0; | ||||||
|  | 
 | ||||||
|  |     if (cmdname) | ||||||
|  |         *cmdname = NULL; | ||||||
|  |     if (cmdargs) | ||||||
|  |         *cmdargs = NULL; | ||||||
|  | 
 | ||||||
|  |     if (pid == -1) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     /* Check if /proc/pid/cmdline exists. It's not supported on all
 | ||||||
|  |      * operating systems. */ | ||||||
|  |     if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0) | ||||||
|  |         return; | ||||||
|  |     fd = open(path, O_RDONLY); | ||||||
|  |     if (fd < 0) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     /* Read the contents of /proc/pid/cmdline. It should contain the
 | ||||||
|  |      * process name and arguments. */ | ||||||
|  |     totsize = read(fd, path, sizeof(path)); | ||||||
|  |     if (totsize <= 0) | ||||||
|  |         return; | ||||||
|  |     if (close(fd) < 0) | ||||||
|  |         return; | ||||||
|  |     path[totsize - 1] = '\0'; | ||||||
|  | 
 | ||||||
|  |     /* Contruct the process name without arguments. */ | ||||||
|  |     cmdsize = strlen(path) + 1; | ||||||
|  |     if (cmdname) | ||||||
|  |     { | ||||||
|  |         char *name = malloc(cmdsize); | ||||||
|  |         if (name) | ||||||
|  |         { | ||||||
|  |             strncpy(name, path, cmdsize); | ||||||
|  |             name[cmdsize - 1] = '\0'; | ||||||
|  |             *cmdname = name; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Construct the arguments for client process. */ | ||||||
|  |     argsize = totsize - cmdsize; | ||||||
|  |     if (cmdargs && (argsize > 0)) | ||||||
|  |     { | ||||||
|  |         char *args = malloc(argsize); | ||||||
|  |         if (args) | ||||||
|  |         { | ||||||
|  |             int i = 0; | ||||||
|  |             for (i = 0; i < (argsize - 1); ++i) | ||||||
|  |             { | ||||||
|  |                 const char c = path[cmdsize + i]; | ||||||
|  |                 args[i] = (c == '\0') ? ' ' : c; | ||||||
|  |             } | ||||||
|  |             args[argsize - 1] = '\0'; | ||||||
|  |             *cmdargs = args; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Called when a new client connects. Allocates client ID information. | ||||||
|  |  * | ||||||
|  |  * @param[in] client Recently connected client. | ||||||
|  |  */ | ||||||
|  | void ReserveClientIds(struct _Client *client) | ||||||
|  | { | ||||||
|  | #ifdef CLIENTIDS | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     assert(!client->clientIds); | ||||||
|  |     client->clientIds = calloc(1, sizeof(ClientIdRec)); | ||||||
|  |     if (!client->clientIds) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     client->clientIds->pid = DetermineClientPid(client); | ||||||
|  |     if (client->clientIds->pid != -1) | ||||||
|  |         DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs); | ||||||
|  | 
 | ||||||
|  |     DebugF("client(%lx): Reserved pid(%d).\n", | ||||||
|  |            client->clientAsMask, client->clientIds->pid); | ||||||
|  |     DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n", | ||||||
|  |            client->clientAsMask, | ||||||
|  |            client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", | ||||||
|  |            client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); | ||||||
|  | #endif /* CLIENTIDS */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Called when an existing client disconnects. Frees client ID | ||||||
|  |  * information. | ||||||
|  |  * | ||||||
|  |  * @param[in] client Recently disconnected client. | ||||||
|  |  */ | ||||||
|  | void ReleaseClientIds(struct _Client *client) | ||||||
|  | { | ||||||
|  | #ifdef CLIENTIDS | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (!client->clientIds) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     DebugF("client(%lx): Released pid(%d).\n", | ||||||
|  |            client->clientAsMask, client->clientIds->pid); | ||||||
|  |     DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n", | ||||||
|  |            client->clientAsMask, | ||||||
|  |            client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", | ||||||
|  |            client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); | ||||||
|  | 
 | ||||||
|  |     free((void *) client->clientIds->cmdname); /* const char * */ | ||||||
|  |     free((void *) client->clientIds->cmdargs); /* const char * */ | ||||||
|  |     free(client->clientIds); | ||||||
|  |     client->clientIds = NULL; | ||||||
|  | #endif /* CLIENTIDS */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get cached PID of a client. | ||||||
|  |  * | ||||||
|  |  * param[in] client Client whose PID has been already cached. | ||||||
|  |  * | ||||||
|  |  * @return Cached client PID. Error (-1) if called: | ||||||
|  |  *         - before ClientStateInitial client state notification | ||||||
|  |  *         - after ClientStateGone client state notification | ||||||
|  |  *         - for remote clients | ||||||
|  |  * | ||||||
|  |  * @see DetermineClientPid | ||||||
|  |  */ | ||||||
|  | pid_t GetClientPid(struct _Client *client) | ||||||
|  | { | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|  |     if (!client->clientIds) | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|  |     return client->clientIds->pid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get cached command name string of a client. | ||||||
|  |  * | ||||||
|  |  * param[in] client Client whose command line string has been already | ||||||
|  |  *                  cached. | ||||||
|  |  * | ||||||
|  |  * @return Cached client command name. Error (NULL) if called: | ||||||
|  |  *         - before ClientStateInitial client state notification | ||||||
|  |  *         - after ClientStateGone client state notification | ||||||
|  |  *         - for remote clients | ||||||
|  |  *         - on OS that doesn't support mapping of PID to command line | ||||||
|  |  * | ||||||
|  |  * @see DetermineClientCmd | ||||||
|  |  */ | ||||||
|  | const char *GetClientCmdName(struct _Client *client) | ||||||
|  | { | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     if (!client->clientIds) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     return client->clientIds->cmdname; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get cached command arguments string of a client. | ||||||
|  |  * | ||||||
|  |  * param[in] client Client whose command line string has been already | ||||||
|  |  *                  cached. | ||||||
|  |  * | ||||||
|  |  * @return Cached client command arguments. Error (NULL) if called: | ||||||
|  |  *         - before ClientStateInitial client state notification | ||||||
|  |  *         - after ClientStateGone client state notification | ||||||
|  |  *         - for remote clients | ||||||
|  |  *         - on OS that doesn't support mapping of PID to command line | ||||||
|  |  * | ||||||
|  |  * @see DetermineClientCmd | ||||||
|  |  */ | ||||||
|  | const char *GetClientCmdArgs(struct _Client *client) | ||||||
|  | { | ||||||
|  |     if (client == NullClient) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     if (!client->clientIds) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     return client->clientIds->cmdargs; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue