)]}'
{
  "commit": "c851eb7ccfe5790cf61e58980a4020a7515fdac0",
  "tree": "812db7efa207a3563f32a6e6cfac9b07c26f41c2",
  "parents": [
    "eff294a56406acb033f57450097c21dd5177de6d"
  ],
  "author": {
    "name": "David Howells",
    "email": "dhowells@redhat.com",
    "time": "Thu May 25 17:27:30 2017 +0100"
  },
  "committer": {
    "name": "David Howells",
    "email": "dhowells@redhat.com",
    "time": "Thu Feb 04 17:44:45 2021 +0000"
  },
  "message": "keys: Allow request_key upcalls from a container to be intercepted\n\nProvide a mechanism by which daemons can intercept request_key upcalls,\nfiltered by namespace and key type, and service them.  The list of active\nservices is per-user_namespace.\n\n\n\u003d\u003d\u003d\u003d\nWHY?\n\u003d\u003d\u003d\u003d\n\nRequests to upcall and instantiate a key are directed to /sbin/request_key\nrun in the init namespaces.  This is the wrong thing to do for\nrequest_key() called inside a container.  Rather, the container manager\nshould be able to intercept a request and deal with it itself, applying the\nappropriate namespaces.\n\nFor example, a container with a different network namespace that routes\npackets out of a different NIC should probably not use the main system DNS\nsettings.\n\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nSETTING INTERCEPTS\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nAn intercept is set by calling:\n\n\tkeyctl(KEYCTL_SERVICE_INTERCEPT,\n\t       int queue_keyring, int userns_fd,\n\t       const char *type_name, unsigned int ns_mask);\n\nwhere \"queue_keyring\" indicates a keyring into which authorisation keys\nwill be placed as request_key() calls happen; \"userns_fd\" indicates the\nuser namespace on which to place the interception (or -1 for the caller\u0027s);\n\"type_name\" indicates the type of key to filter for (or NULL); and\n\"ns_mask\" is a bitwise-OR of:\n\n\tKEY_SERVICE_NS_UTS\n\tKEY_SERVICE_NS_IPC\n\tKEY_SERVICE_NS_MNT\n\tKEY_SERVICE_NS_PID\n\tKEY_SERVICE_NS_NET\n\tKEY_SERVICE_NS_CGROUP\n\nwhich select those namespaces of the caller that must match for the\ninterceptionto occur..  So, for example, a daemon that wanted to service\nDNS requests from the kernel would do something like:\n\n\tqueue \u003d add_key(\"keyring\", \"queue\", NULL, 0,\n\t\t\tKEY_SPEC_THREAD_KEYRING);\n\tkeyctl(KEYCTL_SERVICE_INTERCEPT, queue, -1, \"dns_resolver\",\n\t       KEY_SERVICE_NS_NET);\n\nso that it gets all the DNS records issued by processes in the current\nnetwork namespace, no matter what other namespaces are in force at the\ntime.  On the other hand, the following call:\n\n\tkeyctl(KEYCTL_SERVICE_INTERCEPT, queue, -1, NULL, 0);\n\nwill match everything.\n\nIf conflicts arise between two filter records (and different daemons can\nhave filter records in the same list), the most specific record is matched\nby preference, otherwise the first added gets the work.  So, in the example\nabove, the dns_resolver-specific record would match in preference to the\nmatch-everything record as the former in more specific (it specifies a type\nand a particular namespace).  EEXIST is given if an intercept exactly\nmatches one already in place.\n\nAn intercept can be removed by setting queue_keyring to 0, e.g.:\n\n\tkeyctl(KEYCTL_SERVICE_INTERCEPT, 0, -1, \"dns_resolver\",\n\t       KEY_SERVICE_NS_NET);\n\nAll the other parameters must be given as when the intercept was set.\n\nNotes:\n\n (1) Note that anyone can create a channel, but only a sysadmin or the root\n     user of the current user_namespace may add filters.\n\n     [!] NOTE: I\u0027m really not sure how to get the security right here.  Who\n\t is allowed to intercept requests?  Getting it wrong opens a\n\t definite security hole.\n\n (2) It doesn\u0027t really handle multiple service threads watching the same\n     keyring.\n\n (3) The intercepts are not tied to the lifetime of the queue keyring,\n     though they can be removed later.  This is probably wrong, but it\u0027s\n     more tricky since they currently pin the queue keyring.  They are,\n     however, cleaned up when the user namespace that owns then is\n     destroyed.\n\n (4) I\u0027m not sure it really handles cases where some of the caller\u0027s\n     namespaces aren\u0027t owned by the caller\u0027s user_namespace.\n\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nSERVICING REQUESTS\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nThe daemon servicing requests should place a watch on the queue keyring.\nThis will inform it of when an authorisation key is placed in there.\n\nAn authorisation key\u0027s description indicates the target key and the callout\ndata can be read from the authorisation key.\n\nThe daemon can then gain permission to instantiate the associated key.\n\n\tkeyctl_assume_authority(key_id);\n\nAfter which it can do one of:\n\n\tkeyctl_instantiate(key_id, \"foo_bar\", 7, 0);\n\tkeyctl_negate(key_id, 0, 0);\n\tkeyctl_reject(key_id, 0, ENOANO, 0);\n\nand the authorisation key will be automatically revoked and unlinked.\n\nIf the authorisation key is unlinked from all keyrings, the target key will\nbe rejected if it hasn\u0027t been instantiated yet.\n\n\n[!] NOTE: Need to provide some way to find out the operation type and other\n    parameters from the auth key.  /sbin/request_key supplies this on the\n    command line, but I can\u0027t do that here.  It\u0027s probably something that\n    needs storing into the request_key_auth-type key and an additional\n    keyctl providing to retrieve it.\n\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nSAMPLE CODE\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nA sample program is provided.  This can be run as:\n\n\t./samples/watch_queue/key_req_intercept\n\nit will then watch for requests to be made for user keyrings in the user\nnamespace in which it resides.  Such requests can be made by:\n\n\tkeyctl request2 user a @s\n\nThis key will be rejected and the command will fail with ENOANO.\nSubsequent accesses to the key will also fail with ENOANO.\n\nSigned-off-by: David Howells \u003cdhowells@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "7d985a1dfe4af9e4fa38122260f44cfe336b206e",
      "old_mode": 33188,
      "old_path": "include/linux/key-type.h",
      "new_id": "6218688eb25435cf4af774356334e2f5815bc289",
      "new_mode": 33188,
      "new_path": "include/linux/key-type.h"
    },
    {
      "type": "modify",
      "old_id": "64cf8ebdc4ec9434af97ea8a68ff801021378fed",
      "old_mode": 33188,
      "old_path": "include/linux/user_namespace.h",
      "new_id": "7691778aff3ac7d195a678cee01abd123d5762a9",
      "new_mode": 33188,
      "new_path": "include/linux/user_namespace.h"
    },
    {
      "type": "modify",
      "old_id": "4c8884eea8084e8238fcc8aec08e0394aaa86388",
      "old_mode": 33188,
      "old_path": "include/uapi/linux/keyctl.h",
      "new_id": "a2e553df139b1e51c12990449a293aa06d1b46ac",
      "new_mode": 33188,
      "new_path": "include/uapi/linux/keyctl.h"
    },
    {
      "type": "modify",
      "old_id": "78ee75f4cd2107c0ac73f076607b50293470b669",
      "old_mode": 33188,
      "old_path": "kernel/user.c",
      "new_id": "0362d738286a4e726fbe4fe5605b2ec7742f1d50",
      "new_mode": 33188,
      "new_path": "kernel/user.c"
    },
    {
      "type": "modify",
      "old_id": "f60cf7b5973c01d2ac173fd45c86e61c71fb313d",
      "old_mode": 33188,
      "old_path": "kernel/user_namespace.c",
      "new_id": "9aebb4be4c0029e96b2f4b3460a93cf8e9580d69",
      "new_mode": 33188,
      "new_path": "kernel/user_namespace.c"
    },
    {
      "type": "modify",
      "old_id": "c0db3a6bc524d6347e5e125a89fbd040bf6682a6",
      "old_mode": 33188,
      "old_path": "samples/watch_queue/Makefile",
      "new_id": "4aaa2e2f67a0b66162c5dfc974ea1165c527a17c",
      "new_mode": 33188,
      "new_path": "samples/watch_queue/Makefile"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "c187024a0ce063df8fe0218e8b2d1f67ac6591e6",
      "new_mode": 33188,
      "new_path": "samples/watch_queue/key_req_intercept.c"
    },
    {
      "type": "modify",
      "old_id": "5f40807f05b3d1d27cc21d875302af37959ef758",
      "old_mode": 33188,
      "old_path": "security/keys/Makefile",
      "new_id": "3626340df84b5d2ab11f44af0f71c18404fef00e",
      "new_mode": 33188,
      "new_path": "security/keys/Makefile"
    },
    {
      "type": "modify",
      "old_id": "1545efdca56227cde7322379466195433b1890f9",
      "old_mode": 33188,
      "old_path": "security/keys/compat.c",
      "new_id": "39c7b1b2a7c713be82855b680ff6d733ebae3602",
      "new_mode": 33188,
      "new_path": "security/keys/compat.c"
    },
    {
      "type": "modify",
      "old_id": "9b9cf3b6fcbb4d5e57e57100055cee2772d1db40",
      "old_mode": 33188,
      "old_path": "security/keys/internal.h",
      "new_id": "b777ef7556265a9d730c36e16489d7ce7126ed33",
      "new_mode": 33188,
      "new_path": "security/keys/internal.h"
    },
    {
      "type": "modify",
      "old_id": "96a92a645216de09e1870e93ad0464b09f522078",
      "old_mode": 33188,
      "old_path": "security/keys/keyctl.c",
      "new_id": "5cac7979c5c015d5bdb683ff05539845e2c1e6b2",
      "new_mode": 33188,
      "new_path": "security/keys/keyctl.c"
    },
    {
      "type": "modify",
      "old_id": "5e6a907607530e2097ab5a4eba4f19b4d8426f2a",
      "old_mode": 33188,
      "old_path": "security/keys/keyring.c",
      "new_id": "7ab9e5130f1805b994389b7ab714758dd5189ad6",
      "new_mode": 33188,
      "new_path": "security/keys/keyring.c"
    },
    {
      "type": "modify",
      "old_id": "e3d79a7b6db661113eac26533d1182d8da5bf3fd",
      "old_mode": 33188,
      "old_path": "security/keys/process_keys.c",
      "new_id": "3b515781bc8bc8fc6ced1f3908ee63344fbaa02a",
      "new_mode": 33188,
      "new_path": "security/keys/process_keys.c"
    },
    {
      "type": "modify",
      "old_id": "2da4404276f0f5a68b0619dd6aa1d06a0fdb7198",
      "old_mode": 33188,
      "old_path": "security/keys/request_key.c",
      "new_id": "81fe5aa02dee0cd885845f955ce66f290622a535",
      "new_mode": 33188,
      "new_path": "security/keys/request_key.c"
    },
    {
      "type": "modify",
      "old_id": "41e9735006d0c1c8129fe04e03aaa0858f576127",
      "old_mode": 33188,
      "old_path": "security/keys/request_key_auth.c",
      "new_id": "8379dfd1539554a7e5430b4ada496feda2019959",
      "new_mode": 33188,
      "new_path": "security/keys/request_key_auth.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "cea8ae993beafec4e7e86d967f0495fb93868e22",
      "new_mode": 33188,
      "new_path": "security/keys/service.c"
    }
  ]
}
