Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed0ac5c7 authored by David Howells's avatar David Howells
Browse files

keys: Add a keyctl to move a key between keyrings



Add a keyctl to atomically move a link to a key from one keyring to
another.  The key must exist in "from" keyring and a flag can be given to
cause the operation to fail if there's a matching key already in the "to"
keyring.

This can be done with:

	keyctl(KEYCTL_MOVE,
	       key_serial_t key,
	       key_serial_t from_keyring,
	       key_serial_t to_keyring,
	       unsigned int flags);

The key being moved must grant Link permission and both keyrings must grant
Write permission.

flags should be 0 or KEYCTL_MOVE_EXCL, with the latter preventing
displacement of a matching key from the "to" keyring.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent df593ee2
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -577,6 +577,27 @@ The keyctl syscall functions are:
     added.
     added.




  *  Move a key from one keyring to another::

	long keyctl(KEYCTL_MOVE,
		    key_serial_t id,
		    key_serial_t from_ring_id,
		    key_serial_t to_ring_id,
		    unsigned int flags);

     Move the key specified by "id" from the keyring specified by
     "from_ring_id" to the keyring specified by "to_ring_id".  If the two
     keyrings are the same, nothing is done.

     "flags" can have KEYCTL_MOVE_EXCL set in it to cause the operation to fail
     with EEXIST if a matching key exists in the destination keyring, otherwise
     such a key will be replaced.

     A process must have link permission on the key for this function to be
     successful and write permission on both keyrings.  Any errors that can
     occur from KEYCTL_LINK also apply on the destination keyring here.


  *  Unlink a key or keyring from another keyring::
  *  Unlink a key or keyring from another keyring::


	long keyctl(KEYCTL_UNLINK, key_serial_t keyring, key_serial_t key);
	long keyctl(KEYCTL_UNLINK, key_serial_t keyring, key_serial_t key);
+5 −0
Original line number Original line Diff line number Diff line
@@ -310,6 +310,11 @@ extern int key_update(key_ref_t key,
extern int key_link(struct key *keyring,
extern int key_link(struct key *keyring,
		    struct key *key);
		    struct key *key);


extern int key_move(struct key *key,
		    struct key *from_keyring,
		    struct key *to_keyring,
		    unsigned int flags);

extern int key_unlink(struct key *keyring,
extern int key_unlink(struct key *keyring,
		      struct key *key);
		      struct key *key);


+3 −0
Original line number Original line Diff line number Diff line
@@ -67,6 +67,7 @@
#define KEYCTL_PKEY_SIGN		27	/* Create a public key signature */
#define KEYCTL_PKEY_SIGN		27	/* Create a public key signature */
#define KEYCTL_PKEY_VERIFY		28	/* Verify a public key signature */
#define KEYCTL_PKEY_VERIFY		28	/* Verify a public key signature */
#define KEYCTL_RESTRICT_KEYRING		29	/* Restrict keys allowed to link to a keyring */
#define KEYCTL_RESTRICT_KEYRING		29	/* Restrict keys allowed to link to a keyring */
#define KEYCTL_MOVE			30	/* Move keys between keyrings */


/* keyctl structures */
/* keyctl structures */
struct keyctl_dh_params {
struct keyctl_dh_params {
@@ -112,4 +113,6 @@ struct keyctl_pkey_params {
	__u32		__spare[7];
	__u32		__spare[7];
};
};


#define KEYCTL_MOVE_EXCL	0x00000001 /* Do not displace from the to-keyring */

#endif /*  _LINUX_KEYCTL_H */
#endif /*  _LINUX_KEYCTL_H */
+3 −0
Original line number Original line Diff line number Diff line
@@ -159,6 +159,9 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
		return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3),
		return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3),
					  compat_ptr(arg4), compat_ptr(arg5));
					  compat_ptr(arg4), compat_ptr(arg5));


	case KEYCTL_MOVE:
		return keyctl_keyring_move(arg2, arg3, arg4, arg5);

	default:
	default:
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}
+3 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,8 @@ extern void key_type_put(struct key_type *ktype);


extern int __key_link_lock(struct key *keyring,
extern int __key_link_lock(struct key *keyring,
			   const struct keyring_index_key *index_key);
			   const struct keyring_index_key *index_key);
extern int __key_move_lock(struct key *l_keyring, struct key *u_keyring,
			   const struct keyring_index_key *index_key);
extern int __key_link_begin(struct key *keyring,
extern int __key_link_begin(struct key *keyring,
			    const struct keyring_index_key *index_key,
			    const struct keyring_index_key *index_key,
			    struct assoc_array_edit **_edit);
			    struct assoc_array_edit **_edit);
@@ -217,6 +219,7 @@ extern long keyctl_update_key(key_serial_t, const void __user *, size_t);
extern long keyctl_revoke_key(key_serial_t);
extern long keyctl_revoke_key(key_serial_t);
extern long keyctl_keyring_clear(key_serial_t);
extern long keyctl_keyring_clear(key_serial_t);
extern long keyctl_keyring_link(key_serial_t, key_serial_t);
extern long keyctl_keyring_link(key_serial_t, key_serial_t);
extern long keyctl_keyring_move(key_serial_t, key_serial_t, key_serial_t, unsigned int);
extern long keyctl_keyring_unlink(key_serial_t, key_serial_t);
extern long keyctl_keyring_unlink(key_serial_t, key_serial_t);
extern long keyctl_describe_key(key_serial_t, char __user *, size_t);
extern long keyctl_describe_key(key_serial_t, char __user *, size_t);
extern long keyctl_keyring_search(key_serial_t, const char __user *,
extern long keyctl_keyring_search(key_serial_t, const char __user *,
Loading