|
@@ -955,26 +955,23 @@ static bool safe_hardlink_source(struct inode *inode)
|
|
|
* - sysctl_protected_hardlinks enabled
|
|
|
* - fsuid does not match inode
|
|
|
* - hardlink source is unsafe (see safe_hardlink_source() above)
|
|
|
- * - not CAP_FOWNER
|
|
|
+ * - not CAP_FOWNER in a namespace with the inode owner uid mapped
|
|
|
*
|
|
|
* Returns 0 if successful, -ve on error.
|
|
|
*/
|
|
|
static int may_linkat(struct path *link)
|
|
|
{
|
|
|
- const struct cred *cred;
|
|
|
struct inode *inode;
|
|
|
|
|
|
if (!sysctl_protected_hardlinks)
|
|
|
return 0;
|
|
|
|
|
|
- cred = current_cred();
|
|
|
inode = link->dentry->d_inode;
|
|
|
|
|
|
/* Source inode owner (or CAP_FOWNER) can hardlink all they like,
|
|
|
* otherwise, it must be a safe source.
|
|
|
*/
|
|
|
- if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) ||
|
|
|
- capable(CAP_FOWNER))
|
|
|
+ if (inode_owner_or_capable(inode) || safe_hardlink_source(inode))
|
|
|
return 0;
|
|
|
|
|
|
audit_log_link_denied("linkat", link);
|