From: Greg Hudson Date: Tue, 7 Oct 2014 16:12:11 +0000 (-0400) Subject: Use OFD locks where available X-Git-Tag: krb5-1.14-alpha1~188 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0008014a748310e38b3e4d69e3227af935e86cf7;p=thirdparty%2Fkrb5.git 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) --- 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);