mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmUOphQACgkQONu9yGCS aT48SA//UAwiChca8ejeMfb5naUV7yr0r7Vpe32I7+Z+vY+YmuKO2UWOdBi4rvrY +PYIFCA7nfLpp6hXZg14ljX3w1Qh8WftXwlIeml5PJX+/IpyGT2FAx+CcYXAKdQk KqANTdDAogw4wfPF+jY0hqRUP0NuIW2jzPU9cMQHm6/reRs8sSqs9wHo5tqlLLBN YF66O+MyI/FZRwD3HxSeVlaNk1Rrk6I7CtdnXaUqMo7CosagayoiODn5vPMUJXZW I7WOz4hFYJJhvnJKYKCoMUwmpsEQrQwxyeBipfXsoCjdSOn7TBJaTNEqo0cTq1aQ kD34afHBY5cZaS2d0EKFcCYVxRwtzh0N73RuimPNTT3Rfkot9ARFwQjk+eOHrJDh UQlx4aWq2vX400V68LeE6nSxwAoml888mISVrVqeLu4Xzt9dl4JlLD99GC0tu2GG xKZp3BZ2spxEUciGT4Hby3f6PEGO3oJ/m8MSTNsn5wqdeZMbTUQ4O8yWLQZPaacc M+FEHK/beW5inq5mi2hy0rs2uvhbSQoLV79jbS0EeN2x5Z6MTyWfifRqLx1VzvgF oZHw7AeSv97oJGQfqF5j9BIUOC8jMzMircmxY5z/MmWvvjpkoMtTi0Fm66KbR6c/ Ydm83ptyuPg0XotdjlGAc1tGkVQatx7c1XzYqeOhKDBxvY4l13A= =RCAu -----END PGP SIGNATURE----- Merge 4.14.326 into android-4.14-stable Changes in 4.14.326 ARM: pxa: remove use of symbol_get() mmc: au1xmmc: force non-modular build and remove symbol_get usage rtc: ds1685: use EXPORT_SYMBOL_GPL for ds1685_rtc_poweroff modules: only allow symbol_get of EXPORT_SYMBOL_GPL modules USB: serial: option: add Quectel EM05G variant (0x030e) USB: serial: option: add FOXCONN T99W368/T99W373 product HID: wacom: remove the battery when the EKR is off Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race condition serial: sc16is7xx: fix bug when first setting GPIO direction nilfs2: fix general protection fault in nilfs_lookup_dirty_data_buffers() nilfs2: fix WARNING in mark_buffer_dirty due to discarded buffer reuse pinctrl: amd: Don't show `Invalid config param` errors lib/ubsan: remove returns-nonnull-attribute checks 9p: virtio: make sure 'offs' is initialized in zc_request ASoC: da7219: Flush pending AAD IRQ when suspending ethernet: atheros: fix return value check in atl1c_tso_csum() m68k: Fix invalid .section syntax s390/dasd: use correct number of retries for ERP requests fs/nls: make load_nls() take a const parameter ASoc: codecs: ES8316: Fix DMIC config security: keys: perform capable check only on privileged operations net: usb: qmi_wwan: add Quectel EM05GV2 idmaengine: make FSL_EDMA and INTEL_IDMA64 depends on HAS_IOMEM scsi: qedi: Fix potential deadlock on &qedi_percpu->p_work_lock netlabel: fix shift wrapping bug in netlbl_catmap_setlong() bnx2x: fix page fault following EEH recovery sctp: handle invalid error codes without calling BUG() cifs: add a warning when the in-flight count goes negative ALSA: seq: oss: Fix racy open/close of MIDI devices powerpc/32: Include .branch_lt in data section powerpc/32s: Fix assembler warning about r0 udf: Check consistency of Space Bitmap Descriptor udf: Handle error when adding extent to a file Revert "net: macsec: preserve ingress frame ordering" reiserfs: Check the return value from __getblk() fs: Fix error checking for d_hash_and_lookup() cpufreq: powernow-k8: Use related_cpus instead of cpus in driver.exit() regmap: rbtree: Use alloc_flags for memory allocations spi: tegra20-sflash: fix to check return value of platform_get_irq() in tegra_sflash_probe() can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also in case of OOM wifi: mwifiex: Fix OOB and integer underflow when rx packets Bluetooth: nokia: fix value check in nokia_bluetooth_serdev_probe() net: tcp: fix unexcepted socket die when snd_wnd is 0 crypto: caam - fix unchecked return value error lwt: Check LWTUNNEL_XMIT_CONTINUE strictly fs: ocfs2: namei: check return value of ocfs2_add_entry() wifi: mwifiex: fix memory leak in mwifiex_histogram_read() wifi: mwifiex: Fix missed return in oob checks failed path wifi: ath9k: protect WMI command response buffer replacement with a lock wifi: mwifiex: avoid possible NULL skb pointer dereference wifi: ath9k: use IS_ERR() with debugfs_create_dir() net: arcnet: Do not call kfree_skb() under local_irq_disable() netrom: Deny concurrent connect(). ARM: dts: BCM53573: Add cells sizes to PCIe node ARM: dts: samsung: s3c6410-mini6410: correct ethernet reg addresses (split) ARM: dts: samsung: s5pv210-smdkv210: correct ethernet reg addresses (split) drm: adv7511: Fix low refresh rate register for ADV7533/5 of: unittest: fix null pointer dereferencing in of_unittest_find_node_by_name() smackfs: Prevent underflow in smk_set_cipso() audit: fix possible soft lockup in __audit_inode_child() ALSA: ac97: Fix possible error value of *rac97 drivers: clk: keystone: Fix parameter judgment in _of_pll_clk_init() clk: sunxi-ng: Modify mismatched function name PCI: Mark NVIDIA T4 GPUs to avoid bus reset PCI: pciehp: Use RMW accessors for changing LNKCTL wifi: ath10k: Use RMW accessors for changing LNKCTL nfs/blocklayout: Use the passed in gfp flags powerpc/iommu: Fix notifiers being shared by PCI and VIO buses jfs: validate max amount of blocks before allocation. fs: lockd: avoid possible wrong NULL parameter NFSD: da_addr_body field missing in some GETDEVICEINFO replies drivers: usb: smsusb: fix error handling code in smsusb_init_device media: dib7000p: Fix potential division by zero media: dvb-usb: m920x: Fix a potential memory leak in m920x_i2c_xfer() media: cx24120: Add retval check for cx24120_message_send() media: mediatek: vcodec: Return NULL if no vdec_fb is found usb: phy: mxs: fix getting wrong state with mxs_phy_is_otg_host() scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param() scsi: be2iscsi: Add length check when parsing nlattrs scsi: qla4xxx: Add length check when parsing nlattrs x86/APM: drop the duplicate APM_MINOR_DEV macro scsi: qedf: Do not touch __user pointer in qedf_dbg_stop_io_on_error_cmd_read() directly scsi: qedf: Do not touch __user pointer in qedf_dbg_fp_int_cmd_read() directly dma-buf/sync_file: Fix docs syntax media: go7007: Remove redundant if statement USB: gadget: f_mass_storage: Fix unused variable warning cgroup:namespace: Remove unused cgroup_namespaces_init() scsi: core: Use 32-bit hostnum in scsi_host_lookup() scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock serial: tegra: handle clk prepare error in tegra_uart_hw_init() amba: bus: fix refcount leak Revert "IB/isert: Fix incorrect release of isert connection" HID: multitouch: Correct devm device reference for hidinput input_dev name rpmsg: glink: Add check for kstrdup dmaengine: ste_dma40: Add missing IRQ check in d40_probe igmp: limit igmpv3_newpack() packet size to IP_MAX_MTU netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for ip_set_hash_netportnet.c netfilter: xt_u32: validate user space input netfilter: xt_sctp: validate the flag_info count igb: set max size RX buffer when store bad packet is enabled PM / devfreq: Fix leak in devfreq_dev_release() ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl ARM: OMAP2+: Fix -Warray-bounds warning in _pwrdm_state_switch() backlight/gpio_backlight: Compare against struct fb_info.device backlight/bd6107: Compare against struct fb_info.device backlight/lv5207lp: Compare against struct fb_info.device media: dvb: symbol fixup for dvb_attach() ntb: Drop packets when qp link is down ntb: Clean up tx tail index on link down ntb: Fix calculation ntb_transport_tx_free_entry() Revert "PCI: Mark NVIDIA T4 GPUs to avoid bus reset" procfs: block chmod on /proc/thread-self/comm parisc: Fix /proc/cpuinfo output for lscpu dccp: Fix out of bounds access in DCCP error handler X.509: if signature is unsupported skip validation net: handle ARPHRD_PPP in dev_is_mac_header_xmit() pstore/ram: Check start of empty przs during init crypto: stm32 - fix loop iterating through scatterlist for DMA scsi: qla2xxx: fix inconsistent TMF timeout scsi: qla2xxx: Turn off noisy message log fbdev/ep93xx-fb: Do not assign to struct fb_info.dev drm/ast: Fix DRAM init on AST2200 parisc: led: Fix LAN receive and transmit LEDs parisc: led: Reduce CPU overhead for disk & lan LED computation clk: qcom: gcc-mdm9615: use proper parent for pll0_vote clock NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info x86/virt: Drop unnecessary check on extended CPUID level in cpu_has_svm() watchdog: intel-mid_wdt: add MODULE_ALIAS() to allow auto-load pwm: lpc32xx: Remove handling of PWM channels net: read sk->sk_family once in sk_mc_loop() igb: disable virtualization features on 82580 net: ipv6/addrconf: avoid integer underflow in ipv6_create_tempaddr af_unix: Fix data-races around user->unix_inflight. af_unix: Fix data-race around unix_tot_inflight. af_unix: Fix data-races around sk->sk_shutdown. af_unix: Fix data race around sk->sk_err. net: sched: sch_qfq: Fix UAF in qfq_dequeue() kcm: Destroy mutex in kcm_exit_net() igbvf: Change IGBVF_MIN to allow set rx/tx value between 64 and 80 igb: Change IGB_MIN to allow set rx/tx value between 64 and 80 ata: sata_gemini: Add missing MODULE_DESCRIPTION ata: pata_ftide010: Add missing MODULE_DESCRIPTION net: ethernet: mtk_eth_soc: fix possible NULL pointer dereference in mtk_hwlro_get_fdir_all() kcm: Fix memory leak in error path of kcm_sendmsg() ixgbe: fix timestamp configuration code kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg(). parisc: Drop loops_per_jiffy from per_cpu struct autofs: fix memory leak of waitqueues in autofs_catatonic_mode btrfs: output extra debug info if we failed to find an inline backref ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470 hw_breakpoint: fix single-stepping when using bpf_overflow_handler wifi: ath9k: fix printk specifier wifi: mwifiex: fix fortify warning crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui() tpm_tis: Resend command to recover from data transfer errors alx: fix OOB-read compiler warning drm/exynos: fix a possible null-pointer dereference due to data race in exynos_drm_crtc_atomic_disable() md: raid1: fix potential OOB in raid1_remove_disk() ext2: fix datatype of block number in ext2_xattr_set2() fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount() jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount powerpc/pseries: fix possible memory leak in ibmebus_bus_init() media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer() media: af9005: Fix null-ptr-deref in af9005_i2c_xfer media: anysee: fix null-ptr-deref in anysee_master_xfer media: az6007: Fix null-ptr-deref in az6007_i2c_xfer() iio: core: Use min() instead of min_t() to make code more robust media: tuners: qt1010: replace BUG_ON with a regular error media: pci: cx23885: replace BUG with error return usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc scsi: target: iscsi: Fix buffer overflow in lio_target_nacl_info_show() serial: cpm_uart: Avoid suspicious locking kobject: Add sanity check for kset->kobj.ktype in kset_register() md/raid1: fix error: ISO C90 forbids mixed declarations attr: block mode changes of symlinks btrfs: fix lockdep splat and potential deadlock after failure running delayed items nfsd: fix change_info in NFSv4 RENAME replies mtd: rawnand: brcmnand: Fix crash during the panic_write mtd: rawnand: brcmnand: Fix potential false time out warning mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller mtd: rawnand: brcmnand: Fix potential out-of-bounds access in oob write net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-free net/sched: Retire rsvp classifier Linux 4.14.326 Change-Id: I22815ecf1b4b346f889ccaa561b7cb9a20f204ce Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
352 lines
10 KiB
C
352 lines
10 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/fs/attr.c
|
|
*
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
* changes by Thomas Schoebel-Theuer
|
|
*/
|
|
|
|
#include <linux/export.h>
|
|
#include <linux/time.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/string.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <linux/capability.h>
|
|
#include <linux/fsnotify.h>
|
|
#include <linux/fcntl.h>
|
|
#include <linux/security.h>
|
|
#include <linux/evm.h>
|
|
#include <linux/ima.h>
|
|
|
|
/**
|
|
* setattr_prepare - check if attribute changes to a dentry are allowed
|
|
* @dentry: dentry to check
|
|
* @attr: attributes to change
|
|
*
|
|
* Check if we are allowed to change the attributes contained in @attr
|
|
* in the given dentry. This includes the normal unix access permission
|
|
* checks, as well as checks for rlimits and others. The function also clears
|
|
* SGID bit from mode if user is not allowed to set it. Also file capabilities
|
|
* and IMA extended attributes are cleared if ATTR_KILL_PRIV is set.
|
|
*
|
|
* Should be called as the first thing in ->setattr implementations,
|
|
* possibly after taking additional locks.
|
|
*/
|
|
int setattr_prepare(struct dentry *dentry, struct iattr *attr)
|
|
{
|
|
struct inode *inode = d_inode(dentry);
|
|
unsigned int ia_valid = attr->ia_valid;
|
|
|
|
/*
|
|
* First check size constraints. These can't be overriden using
|
|
* ATTR_FORCE.
|
|
*/
|
|
if (ia_valid & ATTR_SIZE) {
|
|
int error = inode_newsize_ok(inode, attr->ia_size);
|
|
if (error)
|
|
return error;
|
|
}
|
|
|
|
/* If force is set do it anyway. */
|
|
if (ia_valid & ATTR_FORCE)
|
|
goto kill_priv;
|
|
|
|
/* Make sure a caller can chown. */
|
|
if ((ia_valid & ATTR_UID) &&
|
|
(!uid_eq(current_fsuid(), inode->i_uid) ||
|
|
!uid_eq(attr->ia_uid, inode->i_uid)) &&
|
|
!capable_wrt_inode_uidgid(inode, CAP_CHOWN))
|
|
return -EPERM;
|
|
|
|
/* Make sure caller can chgrp. */
|
|
if ((ia_valid & ATTR_GID) &&
|
|
(!uid_eq(current_fsuid(), inode->i_uid) ||
|
|
(!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) &&
|
|
!capable_wrt_inode_uidgid(inode, CAP_CHOWN))
|
|
return -EPERM;
|
|
|
|
/* Make sure a caller can chmod. */
|
|
if (ia_valid & ATTR_MODE) {
|
|
if (!inode_owner_or_capable(inode))
|
|
return -EPERM;
|
|
/* Also check the setgid bit! */
|
|
if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
|
|
inode->i_gid) &&
|
|
!capable_wrt_inode_uidgid(inode, CAP_FSETID))
|
|
attr->ia_mode &= ~S_ISGID;
|
|
}
|
|
|
|
/* Check for setting the inode time. */
|
|
if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
|
|
if (!inode_owner_or_capable(inode))
|
|
return -EPERM;
|
|
}
|
|
|
|
kill_priv:
|
|
/* User has permission for the change */
|
|
if (ia_valid & ATTR_KILL_PRIV) {
|
|
int error;
|
|
|
|
error = security_inode_killpriv(dentry);
|
|
if (error)
|
|
return error;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(setattr_prepare);
|
|
|
|
/**
|
|
* inode_newsize_ok - may this inode be truncated to a given size
|
|
* @inode: the inode to be truncated
|
|
* @offset: the new size to assign to the inode
|
|
* @Returns: 0 on success, -ve errno on failure
|
|
*
|
|
* inode_newsize_ok must be called with i_mutex held.
|
|
*
|
|
* inode_newsize_ok will check filesystem limits and ulimits to check that the
|
|
* new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
|
|
* when necessary. Caller must not proceed with inode size change if failure is
|
|
* returned. @inode must be a file (not directory), with appropriate
|
|
* permissions to allow truncate (inode_newsize_ok does NOT check these
|
|
* conditions).
|
|
*/
|
|
int inode_newsize_ok(const struct inode *inode, loff_t offset)
|
|
{
|
|
if (offset < 0)
|
|
return -EINVAL;
|
|
if (inode->i_size < offset) {
|
|
unsigned long limit;
|
|
|
|
limit = rlimit(RLIMIT_FSIZE);
|
|
if (limit != RLIM_INFINITY && offset > limit)
|
|
goto out_sig;
|
|
if (offset > inode->i_sb->s_maxbytes)
|
|
goto out_big;
|
|
} else {
|
|
/*
|
|
* truncation of in-use swapfiles is disallowed - it would
|
|
* cause subsequent swapout to scribble on the now-freed
|
|
* blocks.
|
|
*/
|
|
if (IS_SWAPFILE(inode))
|
|
return -ETXTBSY;
|
|
}
|
|
|
|
return 0;
|
|
out_sig:
|
|
send_sig(SIGXFSZ, current, 0);
|
|
out_big:
|
|
return -EFBIG;
|
|
}
|
|
EXPORT_SYMBOL(inode_newsize_ok);
|
|
|
|
/**
|
|
* setattr_copy - copy simple metadata updates into the generic inode
|
|
* @inode: the inode to be updated
|
|
* @attr: the new attributes
|
|
*
|
|
* setattr_copy must be called with i_mutex held.
|
|
*
|
|
* setattr_copy updates the inode's metadata with that specified
|
|
* in attr. Noticeably missing is inode size update, which is more complex
|
|
* as it requires pagecache updates.
|
|
*
|
|
* The inode is not marked as dirty after this operation. The rationale is
|
|
* that for "simple" filesystems, the struct inode is the inode storage.
|
|
* The caller is free to mark the inode dirty afterwards if needed.
|
|
*/
|
|
void setattr_copy(struct inode *inode, const struct iattr *attr)
|
|
{
|
|
unsigned int ia_valid = attr->ia_valid;
|
|
|
|
if (ia_valid & ATTR_UID)
|
|
inode->i_uid = attr->ia_uid;
|
|
if (ia_valid & ATTR_GID)
|
|
inode->i_gid = attr->ia_gid;
|
|
if (ia_valid & ATTR_ATIME)
|
|
inode->i_atime = timespec_trunc(attr->ia_atime,
|
|
inode->i_sb->s_time_gran);
|
|
if (ia_valid & ATTR_MTIME)
|
|
inode->i_mtime = timespec_trunc(attr->ia_mtime,
|
|
inode->i_sb->s_time_gran);
|
|
if (ia_valid & ATTR_CTIME)
|
|
inode->i_ctime = timespec_trunc(attr->ia_ctime,
|
|
inode->i_sb->s_time_gran);
|
|
if (ia_valid & ATTR_MODE) {
|
|
umode_t mode = attr->ia_mode;
|
|
|
|
if (!in_group_p(inode->i_gid) &&
|
|
!capable_wrt_inode_uidgid(inode, CAP_FSETID))
|
|
mode &= ~S_ISGID;
|
|
inode->i_mode = mode;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(setattr_copy);
|
|
|
|
/**
|
|
* notify_change - modify attributes of a filesytem object
|
|
* @dentry: object affected
|
|
* @iattr: new attributes
|
|
* @delegated_inode: returns inode, if the inode is delegated
|
|
*
|
|
* The caller must hold the i_mutex on the affected object.
|
|
*
|
|
* If notify_change discovers a delegation in need of breaking,
|
|
* it will return -EWOULDBLOCK and return a reference to the inode in
|
|
* delegated_inode. The caller should then break the delegation and
|
|
* retry. Because breaking a delegation may take a long time, the
|
|
* caller should drop the i_mutex before doing so.
|
|
*
|
|
* Alternatively, a caller may pass NULL for delegated_inode. This may
|
|
* be appropriate for callers that expect the underlying filesystem not
|
|
* to be NFS exported. Also, passing NULL is fine for callers holding
|
|
* the file open for write, as there can be no conflicting delegation in
|
|
* that case.
|
|
*/
|
|
int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
|
|
{
|
|
struct inode *inode = dentry->d_inode;
|
|
umode_t mode = inode->i_mode;
|
|
int error;
|
|
struct timespec now;
|
|
unsigned int ia_valid = attr->ia_valid;
|
|
|
|
WARN_ON_ONCE(!inode_is_locked(inode));
|
|
|
|
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
|
|
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
|
return -EPERM;
|
|
}
|
|
|
|
/*
|
|
* If utimes(2) and friends are called with times == NULL (or both
|
|
* times are UTIME_NOW), then we need to check for write permission
|
|
*/
|
|
if (ia_valid & ATTR_TOUCH) {
|
|
if (IS_IMMUTABLE(inode))
|
|
return -EPERM;
|
|
|
|
if (!inode_owner_or_capable(inode)) {
|
|
error = inode_permission2(mnt, inode, MAY_WRITE);
|
|
if (error)
|
|
return error;
|
|
}
|
|
}
|
|
|
|
if ((ia_valid & ATTR_MODE)) {
|
|
/*
|
|
* Don't allow changing the mode of symlinks:
|
|
*
|
|
* (1) The vfs doesn't take the mode of symlinks into account
|
|
* during permission checking.
|
|
* (2) This has never worked correctly. Most major filesystems
|
|
* did return EOPNOTSUPP due to interactions with POSIX ACLs
|
|
* but did still updated the mode of the symlink.
|
|
* This inconsistency led system call wrapper providers such
|
|
* as libc to block changing the mode of symlinks with
|
|
* EOPNOTSUPP already.
|
|
* (3) To even do this in the first place one would have to use
|
|
* specific file descriptors and quite some effort.
|
|
*/
|
|
if (S_ISLNK(inode->i_mode))
|
|
return -EOPNOTSUPP;
|
|
|
|
/* Flag setting protected by i_mutex */
|
|
if (is_sxid(attr->ia_mode))
|
|
inode->i_flags &= ~S_NOSEC;
|
|
}
|
|
|
|
now = current_time(inode);
|
|
|
|
attr->ia_ctime = now;
|
|
if (!(ia_valid & ATTR_ATIME_SET))
|
|
attr->ia_atime = now;
|
|
if (!(ia_valid & ATTR_MTIME_SET))
|
|
attr->ia_mtime = now;
|
|
if (ia_valid & ATTR_KILL_PRIV) {
|
|
error = security_inode_need_killpriv(dentry);
|
|
if (error < 0)
|
|
return error;
|
|
if (error == 0)
|
|
ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
|
|
}
|
|
|
|
/*
|
|
* We now pass ATTR_KILL_S*ID to the lower level setattr function so
|
|
* that the function has the ability to reinterpret a mode change
|
|
* that's due to these bits. This adds an implicit restriction that
|
|
* no function will ever call notify_change with both ATTR_MODE and
|
|
* ATTR_KILL_S*ID set.
|
|
*/
|
|
if ((ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) &&
|
|
(ia_valid & ATTR_MODE))
|
|
BUG();
|
|
|
|
if (ia_valid & ATTR_KILL_SUID) {
|
|
if (mode & S_ISUID) {
|
|
ia_valid = attr->ia_valid |= ATTR_MODE;
|
|
attr->ia_mode = (inode->i_mode & ~S_ISUID);
|
|
}
|
|
}
|
|
if (ia_valid & ATTR_KILL_SGID) {
|
|
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
|
|
if (!(ia_valid & ATTR_MODE)) {
|
|
ia_valid = attr->ia_valid |= ATTR_MODE;
|
|
attr->ia_mode = inode->i_mode;
|
|
}
|
|
attr->ia_mode &= ~S_ISGID;
|
|
}
|
|
}
|
|
if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID)))
|
|
return 0;
|
|
|
|
/*
|
|
* Verify that uid/gid changes are valid in the target
|
|
* namespace of the superblock.
|
|
*/
|
|
if (ia_valid & ATTR_UID &&
|
|
!kuid_has_mapping(inode->i_sb->s_user_ns, attr->ia_uid))
|
|
return -EOVERFLOW;
|
|
if (ia_valid & ATTR_GID &&
|
|
!kgid_has_mapping(inode->i_sb->s_user_ns, attr->ia_gid))
|
|
return -EOVERFLOW;
|
|
|
|
/* Don't allow modifications of files with invalid uids or
|
|
* gids unless those uids & gids are being made valid.
|
|
*/
|
|
if (!(ia_valid & ATTR_UID) && !uid_valid(inode->i_uid))
|
|
return -EOVERFLOW;
|
|
if (!(ia_valid & ATTR_GID) && !gid_valid(inode->i_gid))
|
|
return -EOVERFLOW;
|
|
|
|
error = security_inode_setattr(dentry, attr);
|
|
if (error)
|
|
return error;
|
|
error = try_break_deleg(inode, delegated_inode);
|
|
if (error)
|
|
return error;
|
|
|
|
if (mnt && inode->i_op->setattr2)
|
|
error = inode->i_op->setattr2(mnt, dentry, attr);
|
|
else if (inode->i_op->setattr)
|
|
error = inode->i_op->setattr(dentry, attr);
|
|
else
|
|
error = simple_setattr(dentry, attr);
|
|
|
|
if (!error) {
|
|
fsnotify_change(dentry, ia_valid);
|
|
ima_inode_post_setattr(dentry);
|
|
evm_inode_post_setattr(dentry, ia_valid);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL(notify_change2);
|
|
|
|
int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
|
|
{
|
|
return notify_change2(NULL, dentry, attr, delegated_inode);
|
|
}
|
|
EXPORT_SYMBOL(notify_change);
|