Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 9 Aug 2019 10:48:18 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: [RFC] final time64 switch-over patch series

On Fri, Aug 02, 2019 at 05:44:33PM -0400, Rich Felker wrote:
> 2. the rusage, utmpx, and timex structs are not correct with regard to
> ABI or functionality. they need to be fixed before this is safe to
> use.

There's also struct sched_param, which contains gratuitous timespecs
for functionality we don't (and probably won't ever) support. This
will gratuitously change size when we change time_t unless action is
taken to prevent it.

My leaning here is to just remove all the sched_ss_* stuff and replace
it with same-sized reserved space. But nothing in libc accesses (read
or write) anything but a single int (sched_prio) via the sched_param
pointer, so we could just leave it and let the size change; this would
not affect any ABI between libc and the libc-consumer, but it would
affect ABI between pairs of libc-consumers using the type (which seems
pretty far-fetched. Also, we would never be able to access the
additional space it's expanded to, because the caller could plausibly
be an old binary that allocated less space. So I think just getting
rid of it all is best.

Note that we lack a proper type (what would essentially be
"__old_time_t") to define same-size replacement for the members to be
removed and replaced with "reserved" space. This is the same type we
need in rusage, timex, and possibly utmpx as well.

I could make alltypes.h define __OLD_TIME_T or something, and
conditionally use it if it's defined. But I think it may be cleaner to
use _REDIR_TIME64 as a proxy for this. If _REDIR_TIME64 is defined,
that means there's an old ABI to be matched, and "old time_t"
necessarily has type long, which is necessarily 32-bit in such a case.
So it could be something like:

struct sched_param {
	int sched_priority;
	int __reserved1;
#if _REDIR_TIME64
	long __reserved2[4];
#else
	long long __reserved2[4];
#endif
	int __reserved3;
};

Note that the only reason this is needed is x32; otherwise, long would
always be the right size to match the old time_t. But in the other
places, it's more useful:

struct rusage {
#if _REDIR_TIME64
	struct {
		long tv_sec, tv_usec;
	} __ru_utime32, __ru_stime32;
#else
	struct timeval ru_utime;
	struct timeval ru_stime;
#endif
	/* linux extentions, but useful */
	long	ru_maxrss;
	long	ru_ixrss;
	long	ru_idrss;
	long	ru_isrss;
	long	ru_minflt;
	long	ru_majflt;
	long	ru_nswap;
	long	ru_inblock;
	long	ru_oublock;
	long	ru_msgsnd;
	long	ru_msgrcv;
	long	ru_nsignals;
	long	ru_nvcsw;
	long	ru_nivcsw;
#if _REDIR_TIME64
	long    __reserved[8];
	struct timeval ru_utime;
	struct timeval ru_stime;
#else
	long    __reserved[16];
#endif
};

Note that using the reserved space to avoid increasing the size here
isn't really useful, since the alignment requirement may change too
due to introduction of 64-bit members, but it might make things more
robust against ABI mismatches (likely SIGBUS instead of OOB
load/store).

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.