From patchwork Wed Oct 9 16:29:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 1173860 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=googlegroups.com (client-ip=2a00:1450:4864:20::53a; helo=mail-ed1-x53a.google.com; envelope-from=swupdate+bncbaabbdew7dwakgqeqfv7loq@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=siemens.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b="aNYFGeNQ"; dkim-atps=neutral Received: from mail-ed1-x53a.google.com (mail-ed1-x53a.google.com [IPv6:2a00:1450:4864:20::53a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46pKSb4D3Jz9sNF for ; Thu, 10 Oct 2019 03:30:07 +1100 (AEDT) Received: by mail-ed1-x53a.google.com with SMTP id l9sf1757204edi.8 for ; Wed, 09 Oct 2019 09:30:07 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1570638604; cv=pass; d=google.com; s=arc-20160816; b=TZAiBWaqHkzYFT5D7YYPmGco1KT0KDUZLk36SJtOGyq7HnXWIdZSNmF89o56K4CE7R UvVQ72Vn1GToO62DQtgPW1edbGSMe+Qvb70D4qODFeLKNhDC5E204NITebImgBdnnLdC e5PNrCXreXV0Mi62uEXI88BhSXKH5EMbvoS/Zrtw0t7lymu1JLF5L3tbTt2ntyQPRVOo 4tAiApByg7SGREZ3xSZnZAWkDWeeghLUP5FK/PjuARHcXU5naBd8COP//yLu3YxZiaU8 g0znbhh306lz42rRkP9cgAtQJ4Ktri9kMnQ6R8HB38RYolCljatlv6mXSwBjj1IimAT8 afEw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:mime-version:sender:dkim-signature; bh=g8K03zpVayhnYDOFs9u7V6ixh0zacQHNteb6Yy8c1OI=; b=NH3RRkTzeCLFy1OEPlHFoNdZEss9ljWvxjDAVCVdRUn1wb4sfux6koirPUaYQ047Rv 6URSfnKibq5Ey4mBzGUbxLR0DUqnC4P9cb7//ggWqZgWCoe2X0KTe2MbZJ7sJ6sAJa5R G1tPXYexHCaCEmUGbucFN/61QjLgFl8Jgv5uiOtKjwnY2uH4e/Yb2WuVBhsfSZR9eohg o20OrvFPNq8ESWjyZUPG7vGHJld+l2UwT65Po9h4+JgmOHg84q89MhXTEK9Af2DpL9e1 u9vhDKwnpKy6uZOel6/QZ8pd7Pbwa0lQyP0xxAMW1sszG3zr9Fu6B6zKpOxySRCKJd40 FcOA== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=pass (google.com: domain of adrian.freihofer@siemens.com designates 192.35.17.2 as permitted sender) smtp.mailfrom=adrian.freihofer@siemens.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=g8K03zpVayhnYDOFs9u7V6ixh0zacQHNteb6Yy8c1OI=; b=aNYFGeNQA5mGZDlBWjzqcy0R7ddWROD+89gZYyVjQsdjuY5UXNBC8iTCiZHCBuYIJm mbMcqNBhMXzjZP2EXHaZHFrZ0ucC6t2uCoukr8UbAHSXI0RkozFPTelRQBlbMux56Zpi i1jJipstvY7njfbwsHY1w0+toaflpq/V+9TUlMafU7t1Mcqy/xLSob1avoHcWtk5WXPz omerG2zVakIZIS2yfU8tSouf4gzQwYT86LAc7Z8QguoTuadOVrztOu1UZ+X3ldB3Bx4q Twa1RGcQplTxcNCucdYKALP7WrB8XDkw1QaeuJAybUn2dvWaHCqnXJb+nHxuGxE2XHtu iX3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:mime-version:from:to:cc:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=g8K03zpVayhnYDOFs9u7V6ixh0zacQHNteb6Yy8c1OI=; b=akeSKDf432mpiI/qazVaXpjFBa6MIx1QRZkyJmxBD1jMTmfJbb7tM3ivLMf1gCOX3i HIxNBSJ/AkwBxEypfsgyuYJvg0d1SxzPIGJBXgkIbEwAk0cBoFQNeZjdapqpuEIHTH7z SxeJwr5bZKsSWhEFXRaLbSH+yb3i2cMlMepSipIYcabhKM85rJIiNlRjsQpk89N1MmQA +Bdm82VM7tt89BkUrZRXQl94pIR7i7GIjqxkrs0kquYzT9shVhUbjQoLWbV2KawtaPjE QheJ6rRctkad1gthEghCq02PmNjt6SsWgBype+I8n74A+sa1cakdvQphV31D5tRn6evB 9MZQ== Sender: swupdate@googlegroups.com X-Gm-Message-State: APjAAAWdGXGabM3/oGgMkcQlmBTsQGdU3QEW+OlIZt5b1Dpz35ohbcwU n9TdgE4GfN6wRgfZZMEFJRc= X-Google-Smtp-Source: APXvYqw/vVjoq84sx7xO/Qm+srN4bt+7WIBQg2HMqGPS7aOaarJmtC+htg+pob6SDMMxeIEhzILVqQ== X-Received: by 2002:a17:907:20c8:: with SMTP id qq8mr3612854ejb.311.1570638604581; Wed, 09 Oct 2019 09:30:04 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: swupdate@googlegroups.com Received: by 2002:a17:906:69c6:: with SMTP id g6ls231082ejs.10.gmail; Wed, 09 Oct 2019 09:30:04 -0700 (PDT) X-Received: by 2002:a17:906:e89:: with SMTP id p9mr3612214ejf.95.1570638604127; Wed, 09 Oct 2019 09:30:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1570638604; cv=none; d=google.com; s=arc-20160816; b=trBxIbQHy0h9bzM9kT4uTXqevbgr9Ruyy7dIS8nrp1cHaTz5mkUhKvzBwmuJnhG5nr ioFFgq+H1ttqamt7nPHoMECQdJ4lT8W8dMKVAOpQPJrB5UFSCbGuk2GYNubac8ZTfzIT h/ezIL84RJ+Gpp5FIumKAPReDD6Wuxpx4XDZ4ZuHIhq61JnUUWq4GhPywDyPENs5oexh gjcG4/o/Xi5HEs9JSFhETrXeAnQqyPoTg+ewrT1OP4IRkuOACF+EozlHI2x5XdfqkHRn 2/eQz5d2gqK0XFheR6xktXdczlhG4VLIgFnZ4LkyUKlQoy7RqIw/3RQE5/UGCHux5V6a KJSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from; bh=K7NAjfc2VjD2jlnsygg93QkJgVqUjyhwLYoyDoxWwgw=; b=ptEeWzqY1O65mOaam15plYNXXzjGFMlWzgwniHulZ0VePewo/UDDBC2Eq/8Mbnu4am zxuyzHbNg0R8lMGAU0POIwf2FW83HpEZpkACqKDZ3o/1bDc3tfTDk7VUa0ciS3LSJRzK doKu3dUKKFNjT4sQJxFVhz0txtMbx0cbLqnprzlPN4vqlLDNRHDGdF6Il3cBVfDXr1Ni 2PIdIAUUaDou5XpByXl4Vbo1qWd2zweIlLzkk5Y8eof5w/JJuyFjU3rCML6+5n8agYUD J3Y3wdLfUQGAXibjMUAABtTQ8joW/46nZPIq7YNAl2iabwx4Z7QaXjJVR3uUI5YrbCxG ySIQ== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=pass (google.com: domain of adrian.freihofer@siemens.com designates 192.35.17.2 as permitted sender) smtp.mailfrom=adrian.freihofer@siemens.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: from thoth.sbs.de (thoth.sbs.de. [192.35.17.2]) by gmr-mx.google.com with ESMTPS id q8si207531edn.5.2019.10.09.09.30.04 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 09 Oct 2019 09:30:04 -0700 (PDT) Received-SPF: pass (google.com: domain of adrian.freihofer@siemens.com designates 192.35.17.2 as permitted sender) client-ip=192.35.17.2; Received: from mail3.siemens.de (mail3.siemens.de [139.25.208.14]) by thoth.sbs.de (8.15.2/8.15.2) with ESMTPS id x99GU3cW020634 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 9 Oct 2019 18:30:03 +0200 Received: from dev.vm6.ccp.siemens.com ([167.87.35.110]) by mail3.siemens.de (8.15.2/8.15.2) with ESMTP id x99GU2WN000388; Wed, 9 Oct 2019 18:30:02 +0200 Received: from dev.localdomain (localhost [127.0.0.1]) by dev.vm6.ccp.siemens.com (Postfix) with ESMTP id A5DF52353A50; Wed, 9 Oct 2019 18:30:01 +0200 (CEST) From: Adrian Freihofer To: swupdate@googlegroups.com Cc: Adrian Freihofer Subject: [swupdate] [[libubootenv] v2 3/3] handle protected mmcblk_boot_ devices Date: Wed, 9 Oct 2019 18:29:34 +0200 Message-Id: <20191009162934.20998-4-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20191009162934.20998-1-adrian.freihofer@siemens.com> References: <20191009162934.20998-1-adrian.freihofer@siemens.com> X-Original-Sender: adrian.freihofer@siemens.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of adrian.freihofer@siemens.com designates 192.35.17.2 as permitted sender) smtp.mailfrom=adrian.freihofer@siemens.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Some block devices support physical write protection. The kernel provides a standard interface to enable or disable protection in /sys/class/block/*/force_ro. This patch adds functionality to automatically detect these memory types. If read-only mode is enabled on the partition on which the uboot environment must be written, libubootenv temporarily switches to read/write mode. Signed-off-by: Adrian Freihofer --- src/CMakeLists.txt | 2 + src/mmcblkboot_ro.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mmcblkboot_ro.h | 11 +++++ src/uboot_env.c | 23 +++++++++ 4 files changed, 171 insertions(+) create mode 100644 src/mmcblkboot_ro.c create mode 100644 src/mmcblkboot_ro.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 051732b..0b7aeaf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required (VERSION 2.6) SET(libubootenv_SOURCES uboot_env.c uboot_private.h + mmcblkboot_ro.c + mmcblkboot_ro.h ) # Public headers diff --git a/src/mmcblkboot_ro.c b/src/mmcblkboot_ro.c new file mode 100644 index 0000000..f9f768e --- /dev/null +++ b/src/mmcblkboot_ro.c @@ -0,0 +1,135 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * For some block device types, the uboot environment variables are stored in + * a read-only partition. The kernel provides an interface + * /sys/class/block/mmcblk?boot?/force_ro to enable and disable the write only + * flag. + * + * The reprotect function does not enable write protection if the memory was + * not protected before the unprotect function was called. + */ + +#include +#include +#include +#include +#include +#include +#include "mmcblkboot_ro.h" + +typedef void (*fp_unprotect)(env_protect_mmcblkboot_t*); +typedef void (*fp_reprotect)(env_protect_mmcblkboot_t*); + + +#define SYSFS_PATH_MAX 120 + +static const char c_sys_path_1[] = "/sys/class/block/"; +static const char c_sys_path_2[] = "/force_ro"; +static const char c_dev_name_1[] = "mmcblk"; +static const char c_dev_name_2[] = "boot"; + +/** mmcblk_boot device specific class */ +typedef struct env_protect_mmcblkboot { + fp_unprotect unprotect; + fp_reprotect reprotect; + char sysfs_path[SYSFS_PATH_MAX]; + char current_prot; +} env_protect_mmcblkboot_t; + +/** Enables read/write mode for the given device */ +void mmcblkboot_unprotect(env_protect_mmcblkboot_t *p_obj) { + const char c_unprot_char = '0'; + const char c_prot_char = '1'; + int fd; + ssize_t n; + + fd = open(p_obj->sysfs_path, O_RDWR); + if (fd == -1) { + return; + } + + // Verify and archive the current write protect state, unprotect the device + n = read(fd, &(p_obj->current_prot), 1); + if (n == 1 && (p_obj->current_prot == c_unprot_char || p_obj->current_prot == c_prot_char)) { + write(fd, &c_unprot_char, 1); + } else { + p_obj->current_prot = 0; // undefined state + } + close(fd); +} + +/** re-activates the read only protection + * + * if it has been removed by the previous unprotect call. + * + */ +void mmcblkboot_reprotect(env_protect_mmcblkboot_t *p_obj) { + int fd; + + if (p_obj->current_prot != 0) { + fd = open(p_obj->sysfs_path, O_WRONLY); + if (fd == -1) { + return; + } + write(fd, &(p_obj->current_prot), 1); + close(fd); + } +} + +/** + * constructor of env_protect_mmcblkboot_t + * + * Creates an oject assigned to pp_obj if: + * - devname matches /dev/mmcblk[0-9]boot[0-9] + * - if a corresponding sysfs entry "force_ro" exists + * It returns 1 of the device needs to be unprotected, 0 if not. In case of an error, + * a negative error code is returned. + */ +int mmcblkboot_create(env_protect_mmcblkboot_t **pp_obj, const char *devname) { + env_protect_mmcblkboot_t *p_obj = NULL; + const char *devfile = devname; + int ret; + + if (strncmp("/dev/", devname, 5) == 0) { + devfile = devname + 5; + } else { + return 0; + } + + ret = strncmp(devfile, c_dev_name_1, sizeof(c_dev_name_1) - 1); + if (ret != 0) { + return 0; + } + + if (strncmp(devfile + sizeof(c_dev_name_1), c_dev_name_2, sizeof(c_dev_name_2) - 1) != 0) { + return 0; + } + + if (*(devfile + sizeof(c_dev_name_1) - 1) < '0' || + *(devfile + sizeof(c_dev_name_1) - 1) > '9') { + return 0; + } + + if (*(devfile + sizeof(c_dev_name_1) + sizeof(c_dev_name_2) - 1) < '0' || + *(devfile + sizeof(c_dev_name_1) + sizeof(c_dev_name_2) - 1) > '9') { + return 0; + } + + p_obj = (env_protect_mmcblkboot_t *)calloc(1, sizeof(env_protect_mmcblkboot_t)); + if (p_obj == NULL) { + return -ENOMEM; + } + snprintf(p_obj->sysfs_path, SYSFS_PATH_MAX, "%s%s%s", c_sys_path_1, devfile, c_sys_path_2); + + if (access(p_obj->sysfs_path, W_OK) == -1) { + free(p_obj); + return 0; + } + + p_obj->unprotect = mmcblkboot_unprotect; + p_obj->reprotect = mmcblkboot_reprotect; + + *pp_obj = p_obj; + return 1; +} diff --git a/src/mmcblkboot_ro.h b/src/mmcblkboot_ro.h new file mode 100644 index 0000000..b86c7d7 --- /dev/null +++ b/src/mmcblkboot_ro.h @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +typedef struct env_protect_mmcblkboot env_protect_mmcblkboot_t; + +int mmcblkboot_create(env_protect_mmcblkboot_t **pp_obj, const char *devname); +void mmcblkboot_unprotect(env_protect_mmcblkboot_t *p_obj); +void mmcblkboot_reprotect(env_protect_mmcblkboot_t *p_obj); diff --git a/src/uboot_env.c b/src/uboot_env.c index 726c433..4281468 100644 --- a/src/uboot_env.c +++ b/src/uboot_env.c @@ -35,6 +35,7 @@ #include #include "uboot_private.h" +#include "mmcblkboot_ro.h" #define DEVICE_MTD_NAME "/dev/mtd" #define DEVICE_UBI_NAME "/dev/ubi" @@ -491,12 +492,34 @@ static int devread(struct uboot_ctx *ctx, unsigned int copy, void *data) static int filewrite(struct uboot_flash_env *dev, void *data) { int ret; + env_protect_mmcblkboot_t *prot_handler = NULL; + + // remove hardware write protection if needed + ret = mmcblkboot_create(&prot_handler, dev->devname); + if(ret < 0) { + goto filewrite_out; + } + if (prot_handler) { + mmcblkboot_unprotect(prot_handler); + } if (dev->offset) lseek(dev->fd, dev->offset, SEEK_SET); ret = write(dev->fd, data, dev->envsize); + // ensure all data are written before we might enable the read-only flag on the environment + fsync(dev->fd); + + // enforce hardware write protection again if it was active before this write + if (prot_handler) { + mmcblkboot_reprotect(prot_handler); + } + +filewrite_out: + if (prot_handler) { + free(prot_handler); + } return ret; }