* Check permissions of file to execute. * Called with imgp->vp locked. * Return 0 for success or error code on failure. */
| 1737 | * Return 0 for success or error code on failure. |
| 1738 | */ |
| 1739 | int |
| 1740 | exec_check_permissions(struct image_params *imgp) |
| 1741 | { |
| 1742 | struct vnode *vp = imgp->vp; |
| 1743 | struct vattr *attr = imgp->attr; |
| 1744 | struct thread *td; |
| 1745 | int error; |
| 1746 | |
| 1747 | td = curthread; |
| 1748 | |
| 1749 | /* Get file attributes */ |
| 1750 | error = VOP_GETATTR(vp, attr, td->td_ucred); |
| 1751 | if (error) |
| 1752 | return (error); |
| 1753 | |
| 1754 | #ifdef MAC |
| 1755 | error = mac_vnode_check_exec(td->td_ucred, imgp->vp, imgp); |
| 1756 | if (error) |
| 1757 | return (error); |
| 1758 | #endif |
| 1759 | |
| 1760 | /* |
| 1761 | * 1) Check if file execution is disabled for the filesystem that |
| 1762 | * this file resides on. |
| 1763 | * 2) Ensure that at least one execute bit is on. Otherwise, a |
| 1764 | * privileged user will always succeed, and we don't want this |
| 1765 | * to happen unless the file really is executable. |
| 1766 | * 3) Ensure that the file is a regular file. |
| 1767 | */ |
| 1768 | if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || |
| 1769 | (attr->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0 || |
| 1770 | (attr->va_type != VREG)) |
| 1771 | return (EACCES); |
| 1772 | |
| 1773 | /* |
| 1774 | * Zero length files can't be exec'd |
| 1775 | */ |
| 1776 | if (attr->va_size == 0) |
| 1777 | return (ENOEXEC); |
| 1778 | |
| 1779 | /* |
| 1780 | * Check for execute permission to file based on current credentials. |
| 1781 | */ |
| 1782 | error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); |
| 1783 | if (error) |
| 1784 | return (error); |
| 1785 | |
| 1786 | /* |
| 1787 | * Check number of open-for-writes on the file and deny execution |
| 1788 | * if there are any. |
| 1789 | * |
| 1790 | * Add a text reference now so no one can write to the |
| 1791 | * executable while we're activating it. |
| 1792 | * |
| 1793 | * Remember if this was set before and unset it in case this is not |
| 1794 | * actually an executable image. |
| 1795 | */ |
| 1796 | error = VOP_SET_TEXT(vp); |
no test coverage detected