From patchwork Thu Nov 9 11:27:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthias Gerstner X-Patchwork-Id: 10050823 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 42439601EA for ; Thu, 9 Nov 2017 11:27:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 31E9D2AC4F for ; Thu, 9 Nov 2017 11:27:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26D2C2AC56; Thu, 9 Nov 2017 11:27:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 839512AC4F for ; Thu, 9 Nov 2017 11:27:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753728AbdKIL13 (ORCPT ); Thu, 9 Nov 2017 06:27:29 -0500 Received: from mx2.suse.de ([195.135.220.15]:44295 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753451AbdKIL12 (ORCPT ); Thu, 9 Nov 2017 06:27:28 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 13DAFAC9B for ; Thu, 9 Nov 2017 11:27:27 +0000 (UTC) Date: Thu, 9 Nov 2017 12:27:22 +0100 From: Matthias Gerstner To: linux-integrity@vger.kernel.org Subject: btrfs UUID all zero (was: [Linux-ima-user] [PATCH] evmctl: use /proc/self/mountinfo instead of /dev/block/:]) Message-ID: <20171109112722.4na4niefjj3uwon4@f195.suse.de> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20170421 (1.8.2) Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hello, referring to my own patch suggestion I've sent to the former linux-ima-user list I have a question regarding IMA and btrfs uuid calculation. My patch below does fix the error message 'evmctl' gives for files located on btrfs. But the resulting EVM digest / HMAC is not agreed upon by the kernel side code. btrfs complicates things by having UUIDs for subvolumes, too. After looking a bit deeper into this I found out that in kernel function hmac_add_misc() the inode->i_sb->s_uuid is all zero for btrfs file systems. I was able to get things to work by passing -u00000000-0000-0000-0000-000000000000 to 'evmctl'. I tested this on kernel version 4.4 and 4.12. My question is if anyone knows whether this zero UUID is a known limitation produced by btrfs. If so then the correct patch to evmctl would be to implicitly use all zero UUIDs for files located on btrfs file systems. Regards Matthias diff --git a/src/evmctl.c b/src/evmctl.c index c54efbb..3baa965 100644 --- a/src/evmctl.c +++ b/src/evmctl.c @@ -276,25 +276,90 @@ static int pack_uuid(const char *uuid_str, char *uuid) return 0; } +#define MAJ_MIN_COL 3 +#define MOUNT_SOURCE_COL 10 + +static int get_blk_dev(dev_t dev, char *path, size_t size) +{ + /* + * Looking in /dev/block/: does not suffice for some + * special file systems like btrfs or overlayfs, because their st_dev + * values do not correspond to any named block device. + * + * Instead parse /proc/self/mountinfo for the correct source device. + */ + int ret = -1; + unsigned int maj = major(dev); + unsigned int min = minor(dev); + char line[LINE_MAX]; + char maj_min_val[LINE_MAX]; + size_t print_res = 0; + FILE *mountinfo = fopen("/proc/self/mountinfo", "r"); + + if (!mountinfo) + return -1; + + // comparison string for the column parsing below + print_res = snprintf(maj_min_val, LINE_MAX, "%u:%u", maj, min); + + if (print_res >= LINE_MAX) + { + // buffer to small + ret = -2; + goto out; + } + + while (fgets(line, LINE_MAX, mountinfo) != NULL) + { + size_t column = 0; + char *token, *tmp_line = line; + + while ( (token = strtok(tmp_line, " ")) ) + { + if (tmp_line) + tmp_line = NULL; + column++; + + if (column == MAJ_MIN_COL) + { + if (strcmp(token, maj_min_val) != 0) + // not the device we're looking for + break; + } + else if (column == MOUNT_SOURCE_COL) + { + print_res = snprintf(path, size, "%s", token); + log_debug("dev: %u:%u -> %s\n", maj, min, token); + ret = print_res < size ? 0 : -2; + goto out; + } + } + } + + // not found or read/parse error + ret = -3; +out: + if (mountinfo) + fclose(mountinfo); + + return ret; +} + static int get_uuid(struct stat *st, char *uuid) { - uint32_t dev; - unsigned minor, major; - char path[PATH_MAX], _uuid[37]; + char blkdev[PATH_MAX], cmdline[PATH_MAX], _uuid[37]; FILE *fp; size_t len; if (uuid_str) return pack_uuid(uuid_str, uuid); - dev = st->st_dev; - major = (dev & 0xfff00) >> 8; - minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); + if (get_blk_dev(st->st_dev, blkdev, PATH_MAX) != 0) + goto err; - log_debug("dev: %u:%u\n", major, minor); - sprintf(path, "blkid -s UUID -o value /dev/block/%u:%u", major, minor); + snprintf(cmdline, PATH_MAX, "blkid -s UUID -o value %s", blkdev); - fp = popen(path, "r"); + fp = popen(cmdline, "r"); if (!fp) goto err; @@ -305,7 +370,7 @@ static int get_uuid(struct stat *st, char *uuid) return pack_uuid(_uuid, uuid); err: - log_err("Failed to read UUID. Root access might require.\n"); + log_err("Failed to read UUID. Root access might be required.\n"); return -1; }