From patchwork Wed Aug 14 11:33:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1146975 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-104404-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="qm5HhAiA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 467nXk1QXsz9sN1 for ; Wed, 14 Aug 2019 21:33:57 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; q=dns; s=default; b=C9SLNyj3OtGVciSB7u8xGCdskMZps KrTxyilMvS+Oi/pTMeWt+tosSgrPD+cNo+x+M/8dWJL3Ro7a4cDwnpq1Fyx5WXPg BqZbIqpNoU6Twrnxz1YXHGgdGlrfLHefg0sHYIFfeDPbFnIE7l9XyFca3eHDojpV 2qMrqtiM1HGyDE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; s=default; bh=8I4xACVw7w6gpjcWaVIl0cy/10M=; b=qm5 HhAiA9BbaAieuj1pLh3bDv84ndDyBDqhJ7Xk6eDWwU2FBlubllJrhE07Pye1r8yh +ub6Xb1aMbBFBcLclP22OJ7b9k3pz4olYVs9W35F8NdeojQ4/kd7xIPId2l7gjiT TkB/9DLWFl0zDNq4eoko8i8N35Nw2g0EZRdBWgpI= Received: (qmail 27868 invoked by alias); 14 Aug 2019 11:33:51 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 27860 invoked by uid 89); 14 Aug 2019 11:33:51 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=Foundation X-HELO: mx1.redhat.com From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH] login: Fix updwtmp, updwtmx unlocking Date: Wed, 14 Aug 2019 13:33:37 +0200 Message-ID: <871rxof0by.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) MIME-Version: 1.0 Commit 5a3afa9738f3dbbaf8c0a35665318c1af782111b (login: Replace macro-based control flow with function calls in utmp) introduced a regression because after it, __libc_updwtmp attempts to unlock the wrong file descriptor. 2019-08-14 Florian Weimer * login/utmp_file.c (__libc_updwtmp): Unlock the right file descriptor. * login/Makefile (tests): Add tst-updwtmpx. * login/tst-updwtmpx.c: New file. Reviewed-by: Carlos O'Donell diff --git a/login/Makefile b/login/Makefile index 92535f0aec..f9c4264087 100644 --- a/login/Makefile +++ b/login/Makefile @@ -43,7 +43,7 @@ endif subdir-dirs = programs vpath %.c programs -tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin +tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx # Build the -lutil library with these extra functions. extra-libs := libutil diff --git a/login/tst-updwtmpx.c b/login/tst-updwtmpx.c new file mode 100644 index 0000000000..4eb4a3fbcd --- /dev/null +++ b/login/tst-updwtmpx.c @@ -0,0 +1,108 @@ +/* Basic test coverage for updwtmpx. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + /* Two entries filled with an arbitrary bit pattern. */ + struct utmpx entries[2]; + unsigned char pad; + { + unsigned char *p = (unsigned char *) &entries[0]; + for (size_t i = 0; i < sizeof (entries); ++i) + { + p[i] = i; + } + /* Make sure that the first and second entry and the padding are + different. */ + p[sizeof (struct utmpx)] = p[0] + 1; + pad = p[0] + 2; + } + + char *path; + int fd = create_temp_file ("tst-updwtmpx-", &path); + + /* Used to check that updwtmpx does not leave an open file + descriptor around. */ + struct support_descriptors *descriptors = support_descriptors_list (); + + /* updwtmpx is expected to remove misalignment. Optionally insert + one byte of misalignment at the start and in the middle (after + the first entry). */ + for (int misaligned_start = 0; misaligned_start < 2; ++misaligned_start) + for (int misaligned_middle = 0; misaligned_middle < 2; ++misaligned_middle) + { + if (test_verbose > 0) + printf ("info: misaligned_start=%d misaligned_middle=%d\n", + misaligned_start, misaligned_middle); + + xftruncate (fd, 0); + TEST_COMPARE (pwrite64 (fd, &pad, misaligned_start, 0), + misaligned_start); + + /* Write first entry and check it. */ + errno = 0; + updwtmpx (path, &entries[0]); + TEST_COMPARE (errno, 0); + support_descriptors_check (descriptors); + TEST_COMPARE (xlseek (fd, 0, SEEK_END), sizeof (struct utmpx)); + struct utmpx buffer; + TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), + sizeof (buffer)); + TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), + &buffer, sizeof (buffer)); + + /* Middle mis-alignmet. */ + TEST_COMPARE (pwrite64 (fd, &pad, misaligned_middle, + sizeof (struct utmpx)), misaligned_middle); + + /* Write second entry and check both entries. */ + errno = 0; + updwtmpx (path, &entries[1]); + TEST_COMPARE (errno, 0); + support_descriptors_check (descriptors); + TEST_COMPARE (xlseek (fd, 0, SEEK_END), 2 * sizeof (struct utmpx)); + TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), + sizeof (buffer)); + TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), + &buffer, sizeof (buffer)); + TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), sizeof (buffer)), + sizeof (buffer)); + TEST_COMPARE_BLOB (&entries[1], sizeof (entries[1]), + &buffer, sizeof (buffer)); + } + + support_descriptors_free (descriptors); + free (path); + xclose (fd); + + return 0; +} + +#include diff --git a/login/utmp_file.c b/login/utmp_file.c index 7bd6034af4..5e4e66d1d0 100644 --- a/login/utmp_file.c +++ b/login/utmp_file.c @@ -503,7 +503,7 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) result = 0; unlock_return: - file_unlock (file_fd); + file_unlock (fd); file_lock_restore (&fl); /* Close WTMP file. */