Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S265624AbUABTtj (ORCPT ); Fri, 2 Jan 2004 14:49:39 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S265625AbUABTtj (ORCPT ); Fri, 2 Jan 2004 14:49:39 -0500 Received: from users.ccur.com ([208.248.32.211]:40202 "HELO rudolph.ccur.com") by vger.kernel.org with SMTP id S265624AbUABTt2 (ORCPT ); Fri, 2 Jan 2004 14:49:28 -0500 Date: Fri, 2 Jan 2004 14:49:09 -0500 From: Joe Korty To: akpm@osdl.org, ak@suse.de Cc: torvalds@osdl.org, linux-kernel@vger.kernel.org, albert.cahalan@ccur.com, jim.houston@ccur.com Subject: siginfo_t fracturing, especially for 64/32-bit compatibility mode Message-ID: <20040102194909.GA2990@rudolph.ccur.com> Reply-To: Joe Korty Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5386 Lines: 108 siginfo_t processing is fragile when in 32 bit compatibility mode on a 64 bit processor. The kernel does conversions between 32 and 64 bit versions of siginfo_t and to do this, it must must always know which of the (unioned) fields of siginfo are actually being used. I believe this is the original purpose of the si_code field -- the value in it should directly or indirectly indicate, unambigiously, which of the fields in siginfo_t hold useful values. rt_sigqueueinfo(2) subverts this by reserving a range of si_code values for users, and there is nothing about them to indicate to the kernel which fields of siginfo_t are actually in use. This is not a problem in native mode as rt_sigqueueinfo simply passes the siginfo_t argument through from the sending to the receiving process without looking at or caring about the individual field values. But as compatibility mode must convert and pass individual argument values, it must know what fields are being used in each any every call to rt_sigqueueinfo from a compatibility-mode 32 bit process, and each time a siginfo structure is delivered to a compatibility-mode 32 bit process (whether generated by a rt_sigqueueinfo from a 64 or 32 bit process, or internally by the kernel). A partial solution is to grep all uses of si_code in the kernel and in glibc and tailor the architecture-specific 64 <-> 32 bit siginfo kernel transform routines to current use. But this is fragile as it does not take into account future glibc growth nor other users of rt_sigqueueinfo outside of glibc, such as applications invoking rt_sigqueueinfo directly. Worse, in 2.6.0 and glibc-2.3.2, there are conflicts in current si_code value assignments which affect both compatibility and native mode users. When an application receives one of these siginfo_t's, it cannot in general determine why it got it or which fields in the siginfo_t it should extract and act upon. And when in compatibility mode, the kernel cannot always determine which fields need to be converted and passed on. The current conflicts are: SI_TKILL (used by the 2.6 kernel) and SI_ASYNCNL (used by glibc-2.3.2) both have the same value (-6). If an application is both threaded and is also using async IO, then it when it gets a siginfo with the SI_TKILL / SI_ASYNCNL value then cannot reliably decide which type it is. This may be solvable by changing glibc to define another value for SI_ASYNCNL as this appears to be used only by glibc in some process that is talking to itself. SI_ASYNCIO is used by the kernel USB drivers to return the field si_addr. Glibc also uses SI_ASYNCIO, but this time the fields si_pid, si_uid, and si_value are used. As si_addr is unioned with si_pid and si_uid, it is not possible for both sets to be correctly converted when in compatibility mode, and even if they could be converted, it still is not possible for application to safely determine, when they receive one of these siginfo_t's, which set of fields to extract and use. As glibc's use of SI_ASYNCIO appears entirely internal to itself, it may be best to fix this problem by defining a new SI_ASYNCIO_GLIBC value in glibc and have glibc use that instead of SI_ASYNCIO. Or, if the USB driver usage is new and no applications or libraries are using it yet, a new si_code value could instead be defined for the USB drivers. The 32-bit compatibility mode issues can be prevented from getting any worse by eliminating the existing 'user' si_code value range (grandfathering in all sensible current uses), then creating a new 'user' si_code system in which the caller declares which data fields in siginfo_t are in use. This would operate much like _IO, _IOR, etc do for ioctls. A possible definition: #define __SI_USERMASK 0xff000000 #define __SI_USERCODE 0x20000000 #define __SI_BITMASK 0x00ffff00 #define __SI_PID 0x00800000 /* si_pid */ #define __SI_UID 0x00400000 /* si_uid */ #define __SI_TID 0x00200000 /* si_tid */ #define __SI_OVRUN 0x00100000 /* si_overrun */ #define __SI_PRIV 0x00080000 /* si_sys_private */ #define __SI_INCR 0x00040000 /* si_overrun_incr */ #define __SI_STAT 0x00020000 /* si_status */ #define __SI_UTIME 0x00010000 /* si_utime */ #define __SI_STIME 0x00008000 /* si_stime */ #define __SI_INT 0x00004000 /* si_int */ #define __SI_PTR 0x00002000 /* si_ptr */ #define __SI_ADDR 0x00001000 /* si_addr */ #define __SI_TRAPNO 0x00000800 /* si_trapno */ #define __SI_BAND 0x00000400 /* si_band */ #define __SI_FD 0x00000200 /* si_fd */ #define __SI_CMDMASK 0x000000ff For example, glibc and other users would define any new user si_code values they need by doing something like: #define SI_FASYNCXX (__SI_USERCODE | __SI_UID | __SI_PID | __SI_INT | 17) To work well, si_code values which do not match these new user values or the grandfathered old user values would cause rt_sigqueueinfo to return EINVAL. Also, to work well, copy_siginfo_to_user should be changed to remove the old blanket-copy when si_code < 0 to one that copies just the specified fields (except for the grandfathered values). Regards, Joe - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/