From 0008014a748310e38b3e4d69e3227af935e86cf7 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 7 Oct 2014 12:12:11 -0400 Subject: [PATCH] Use OFD locks where available Linux 3.15 has added OFD locks, which contend with POSIX file locks but are owned by the open file description instead of the process. Use these in krb5_lock_file where available, for safer concurrency behavior. ticket: 8023 (new) --- src/lib/krb5/os/lock_file.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/lib/krb5/os/lock_file.c b/src/lib/krb5/os/lock_file.c index 224e58fbf5..a2f247cd99 100644 --- a/src/lib/krb5/os/lock_file.c +++ b/src/lib/krb5/os/lock_file.c @@ -57,6 +57,30 @@ #endif #endif +#ifdef POSIX_FILE_LOCKS +/* + * Try to use OFD locks where available (e.g. Linux 3.15 and later). OFD locks + * contend with regular POSIX file locks, but are owned by the open file + * description instead of the process, which is much better for thread safety. + * Fall back to regular POSIX locks on EINVAL in case we are running with an + * older kernel than we were built with. + */ +static int +ofdlock(int fd, int cmd, struct flock *lock_arg) +{ +#ifdef F_OFD_SETLKW + int st, ofdcmd; + + assert(cmd == F_SETLKW || cmd == F_SETLK); + ofdcmd = (cmd == F_SETLKW) ? F_OFD_SETLKW : F_OFD_SETLK; + st = fcntl(fd, ofdcmd, lock_arg); + if (st == 0 || errno != EINVAL) + return st; +#endif + return fcntl(fd, cmd, lock_arg); +} +#endif /* POSIX_FILE_LOCKS */ + /*ARGSUSED*/ krb5_error_code krb5_lock_file(krb5_context context, int fd, int mode) @@ -105,7 +129,7 @@ krb5_lock_file(krb5_context context, int fd, int mode) lock_arg.l_whence = 0; lock_arg.l_start = 0; lock_arg.l_len = 0; - if (fcntl(fd, lock_cmd, &lock_arg) == -1) { + if (ofdlock(fd, lock_cmd, &lock_arg) == -1) { if (errno == EACCES || errno == EAGAIN) /* see POSIX/IEEE 1003.1-1988, 6.5.2.4 */ return(EAGAIN); -- 2.47.2