From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sukadev Bhattiprolu Subject: [PATCH 04/17][cr][v4]: Restore file_owner info Date: Mon, 16 Aug 2010 12:43:08 -0700 Message-ID: <1281987801-1293-5-git-send-email-sukadev@linux.vnet.ibm.com> References: <1281987801-1293-1-git-send-email-sukadev@linux.vnet.ibm.com> Cc: Serge Hallyn , Matt Helsley , Dan Smith , John Stultz , Matthew Wilcox , Jamie Lokier , Steven Whitehouse , , Containers To: Oren Laadan Return-path: Received: from e3.ny.us.ibm.com ([32.97.182.143]:41192 "EHLO e3.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755943Ab0HPThw (ORCPT ); Mon, 16 Aug 2010 15:37:52 -0400 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by e3.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id o7GJMcdP009679 for ; Mon, 16 Aug 2010 15:22:38 -0400 Received: from d03av01.boulder.ibm.com (d03av01.boulder.ibm.com [9.17.195.167]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o7GJblPA394160 for ; Mon, 16 Aug 2010 15:37:47 -0400 Received: from d03av01.boulder.ibm.com (loopback [127.0.0.1]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o7GJbaFZ015058 for ; Mon, 16 Aug 2010 13:37:37 -0600 In-Reply-To: <1281987801-1293-1-git-send-email-sukadev@linux.vnet.ibm.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Restore the file-owner information for each 'struct file'. This is essentially is like a new fcntl(F_SETOWN) and fcntl(F_SETSIG) calls, except that the pid, uid, euid and signum values are read from the checkpoint image. Changelog[v4]: - [Oren Laadan]: Sanitize the pid-type field read from checkpoint image. Changelog[v3]: - [Oren Laadan]: Ensure find_vpid() found a valid pid before making it the file owner. Changelog[v2]: - [Matt Helsley, Serge Hallyn]: Don't trust uids in checkpoint image. (added CAP_KILL check) - Check that signal number read from the checkpoint image is valid. (not sure it is required, since its an incomplete check for tampering) Signed-off-by: Sukadev Bhattiprolu --- fs/checkpoint.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 78 insertions(+), 0 deletions(-) diff --git a/fs/checkpoint.c b/fs/checkpoint.c index ce1b4af..be9d39a 100644 --- a/fs/checkpoint.c +++ b/fs/checkpoint.c @@ -618,6 +618,80 @@ static int attach_file(struct file *file) return fd; } +static int restore_file_owner(struct ckpt_ctx *ctx, struct ckpt_hdr_file *h, + struct file *file) +{ + int ret; + struct pid *pid; + uid_t uid, euid; + + uid = h->f_owner_uid; + euid = h->f_owner_euid; + + ckpt_debug("restore_file_owner(): uid %u, euid %u, pid %d, type %d\n", + uid, euid, h->f_owner_pid, h->f_owner_pid_type); + /* + * We can't trust the uids in the checkpoint image and normally need + * CAP_KILL. But if the uids match our ids, should be fine since we + * have access to the file. + * + * TODO: Move this check to __f_setown() ? + */ + ret = -EACCES; + if (!capable(CAP_KILL) && + (uid != current_uid() || euid != current_euid())) { + ckpt_err(ctx, ret, "image uids [%d, %d] don't match current " + "process uids [%d, %d] and no CAP_KILL\n", + uid, euid, current_uid(), current_euid()); + return ret; + } + + ret = -EINVAL; + if (!valid_signal(h->f_owner_signum)) { + ckpt_err(ctx, ret, "Invalid signum %d\n", h->f_owner_signum); + return ret; + } + file->f_owner.signum = h->f_owner_signum; + + switch(h->f_owner_pid_type) { + case PIDTYPE_PID: + case PIDTYPE_PGID: + case PIDTYPE_SID: + break; + default: + ckpt_err(ctx, ret, "Invalid pid-type %d\n", + h->f_owner_pid_type); + return ret; + + } + + rcu_read_lock(); + + /* + * If file had a non-NULL owner and we can't find the owner after + * restart, return error. + */ + pid = find_vpid(h->f_owner_pid); + if (h->f_owner_pid && !pid) + ret = -ESRCH; + else { + /* + * TODO: Do we need 'force' to be 1 here or can it be 0 ? + * 'force' is used to modify the owner, if one is + * already set. Can it be set when we restart an + * application ? + */ + ret = __f_setown(file, pid, h->f_owner_pid_type, uid, euid, 1); + } + + rcu_read_unlock(); + + if (ret < 0) + ckpt_err(ctx, ret, "__fsetown_uid() failed\n"); + + return ret; +} + #define CKPT_SETFL_MASK \ (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) @@ -651,6 +725,10 @@ int restore_file_common(struct ckpt_ctx *ctx, struct file *file, if (ret < 0) return ret; + ret = restore_file_owner(ctx, h, file); + if (ret < 0) + return ret; + /* * Normally f_mode is set by open, and modified only via * fcntl(), so its value now should match that at checkpoint. -- 1.6.0.4