linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Subject: [PATCH] f2fs: support access control via key management
Date: Wed,  9 Mar 2016 16:52:48 -0800	[thread overview]
Message-ID: <1457571168-56724-1-git-send-email-jaegeuk@kernel.org> (raw)

Through this patch, user can assign its key into a specific normal files.
Then, other users who do not have that key cannot open the files.
Later, owner can drop its key from the files for other users to access
the files again.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/f2fs.h  | 20 +++++++++++++++++
 fs/f2fs/file.c  | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/f2fs/xattr.c |  7 ++++++
 fs/f2fs/xattr.h |  1 +
 4 files changed, 97 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index bbe2cd1..cbc115b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -212,6 +212,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
 #define F2FS_IOC_WRITE_CHECKPOINT	_IO(F2FS_IOCTL_MAGIC, 7)
 #define F2FS_IOC_DEFRAGMENT		_IO(F2FS_IOCTL_MAGIC, 8)
 
+#define F2FS_IOC_KEYCTL		_IOW(F2FS_IOCTL_MAGIC, 9, struct f2fs_key)
+
 #define F2FS_IOC_SET_ENCRYPTION_POLICY	FS_IOC_SET_ENCRYPTION_POLICY
 #define F2FS_IOC_GET_ENCRYPTION_POLICY	FS_IOC_GET_ENCRYPTION_POLICY
 #define F2FS_IOC_GET_ENCRYPTION_PWSALT	FS_IOC_GET_ENCRYPTION_PWSALT
@@ -235,6 +237,20 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
 #define F2FS_IOC32_GETVERSION		FS_IOC32_GETVERSION
 #endif
 
+#define F2FS_KEY_SIZE	8
+#define F2FS_KEY_DESC_PREFIX		"f2fs:"
+#define F2FS_KEY_DESC_PREFIX_SIZE	5
+
+enum f2fs_key_mode {
+	F2FS_SET_KEY,
+	F2FS_DROP_KEY,
+};
+
+struct f2fs_key {
+	u8 key[F2FS_KEY_SIZE];
+	u8 mode;
+};
+
 struct f2fs_defragment {
 	u64 start;
 	u64 len;
@@ -358,6 +374,7 @@ struct f2fs_map_blocks {
 #define FADVISE_LOST_PINO_BIT	0x02
 #define FADVISE_ENCRYPT_BIT	0x04
 #define FADVISE_ENC_NAME_BIT	0x08
+#define FADVISE_KEY_BIT		0x10
 
 #define file_is_cold(inode)	is_file(inode, FADVISE_COLD_BIT)
 #define file_wrong_pino(inode)	is_file(inode, FADVISE_LOST_PINO_BIT)
@@ -370,6 +387,9 @@ struct f2fs_map_blocks {
 #define file_clear_encrypt(inode) clear_file(inode, FADVISE_ENCRYPT_BIT)
 #define file_enc_name(inode)	is_file(inode, FADVISE_ENC_NAME_BIT)
 #define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT)
+#define file_has_key(inode)	is_file(inode, FADVISE_KEY_BIT)
+#define file_set_key(inode)	set_file(inode, FADVISE_KEY_BIT)
+#define file_clear_key(inode)	clear_file(inode, FADVISE_KEY_BIT)
 
 #define DEF_DIR_LEVEL		0
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index b41c357..80f6b29 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -21,6 +21,7 @@
 #include <linux/mount.h>
 #include <linux/pagevec.h>
 #include <linux/random.h>
+#include <keys/user-type.h>
 
 #include "f2fs.h"
 #include "node.h"
@@ -438,6 +439,40 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	return 0;
 }
 
+static int validate_access_key(struct inode *inode)
+{
+	u8 full_key_descriptor[F2FS_KEY_DESC_PREFIX_SIZE +
+					(F2FS_KEY_SIZE * 2) + 1];
+	struct key *keyring_key = NULL;
+	u8 key[F2FS_KEY_SIZE];
+	int ret;
+
+	ret = f2fs_getxattr(inode, F2FS_XATTR_INDEX_KEY,
+				F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
+				key, F2FS_KEY_SIZE, NULL);
+	if (ret != F2FS_KEY_SIZE)
+		return -EINVAL;
+
+	memcpy(full_key_descriptor, F2FS_KEY_DESC_PREFIX,
+					F2FS_KEY_DESC_PREFIX_SIZE);
+	sprintf(full_key_descriptor + F2FS_KEY_DESC_PREFIX_SIZE,
+					"%*phN", F2FS_KEY_SIZE, key);
+	full_key_descriptor[F2FS_KEY_DESC_PREFIX_SIZE +
+					(2 * F2FS_KEY_SIZE)] = '\0';
+	keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL);
+	if (IS_ERR(keyring_key))
+		return PTR_ERR(keyring_key);
+
+	if (keyring_key->type != &key_type_logon) {
+		printk_once(KERN_WARNING
+				"%s: key type must be logon\n", __func__);
+		key_put(keyring_key);
+		return -ENOKEY;
+	}
+	key_put(keyring_key);
+	return 0;
+}
+
 static int f2fs_file_open(struct inode *inode, struct file *filp)
 {
 	int ret = generic_file_open(inode, filp);
@@ -453,6 +488,9 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
 	if (f2fs_encrypted_inode(dir) &&
 			!fscrypt_has_permitted_context(dir, inode))
 		return -EPERM;
+
+	if (file_has_key(inode))
+		return validate_access_key(inode);
 	return ret;
 }
 
@@ -1532,6 +1570,35 @@ static bool uuid_is_nonzero(__u8 u[16])
 	return false;
 }
 
+static int f2fs_ioc_keyctl(struct file *filp, unsigned long arg)
+{
+	struct inode *inode = file_inode(filp);
+	struct f2fs_key key;
+	void *value = key.key;
+	int type = XATTR_CREATE;
+
+	if (copy_from_user(&key, (u8 __user *)arg, sizeof(key)))
+		return -EFAULT;
+
+	if (!S_ISREG(inode->i_mode))
+		return -EINVAL;
+
+	if (key.mode == F2FS_DROP_KEY) {
+		int ret = validate_access_key(inode);
+
+		if (ret)
+			return ret;
+
+		value = NULL;
+		type = XATTR_REPLACE;
+	}
+
+	f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+	return f2fs_setxattr(inode, F2FS_XATTR_INDEX_KEY,
+				F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
+				value, F2FS_KEY_SIZE, NULL, type);
+}
+
 static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
 {
 	struct fscrypt_policy policy;
@@ -1845,6 +1912,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return f2fs_ioc_shutdown(filp, arg);
 	case FITRIM:
 		return f2fs_ioc_fitrim(filp, arg);
+	case F2FS_IOC_KEYCTL:
+		return f2fs_ioc_keyctl(filp, arg);
 	case F2FS_IOC_SET_ENCRYPTION_POLICY:
 		return f2fs_ioc_set_encryption_policy(filp, arg);
 	case F2FS_IOC_GET_ENCRYPTION_POLICY:
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 06a72dc..5b02b31 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -550,6 +550,13 @@ static int __f2fs_setxattr(struct inode *inode, int index,
 	if (index == F2FS_XATTR_INDEX_ENCRYPTION &&
 			!strcmp(name, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT))
 		f2fs_set_encrypted_inode(inode);
+	if (index == F2FS_XATTR_INDEX_KEY &&
+			!strcmp(name, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT)) {
+		if (value)
+			file_set_key(inode);
+		else
+			file_clear_key(inode);
+	}
 
 	if (ipage)
 		update_inode(inode, ipage);
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index 79dccc8..cb5282c 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -37,6 +37,7 @@
 #define F2FS_XATTR_INDEX_ADVISE			7
 /* Should be same as EXT4_XATTR_INDEX_ENCRYPTION */
 #define F2FS_XATTR_INDEX_ENCRYPTION		9
+#define F2FS_XATTR_INDEX_KEY			10
 
 #define F2FS_XATTR_NAME_ENCRYPTION_CONTEXT	"c"
 
-- 
2.6.3


             reply	other threads:[~2016-03-10  0:52 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-10  0:52 Jaegeuk Kim [this message]
2016-03-10  2:05 ` [PATCH] f2fs: support access control via key management kbuild test robot
2016-03-10  2:18 ` kbuild test robot
2016-03-15  7:24 ` Christoph Hellwig
2016-03-15 16:37   ` Jaegeuk Kim
2016-03-21 15:39     ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457571168-56724-1-git-send-email-jaegeuk@kernel.org \
    --to=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).