diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/ss/policydb.c | 238 |
1 files changed, 133 insertions, 105 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index a39d38af220b..4ea073eaf8bf 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -655,6 +655,9 @@ static int range_tr_destroy(void *key, void *datum, void *p) | |||
655 | 655 | ||
656 | static void ocontext_destroy(struct ocontext *c, int i) | 656 | static void ocontext_destroy(struct ocontext *c, int i) |
657 | { | 657 | { |
658 | if (!c) | ||
659 | return; | ||
660 | |||
658 | context_destroy(&c->context[0]); | 661 | context_destroy(&c->context[0]); |
659 | context_destroy(&c->context[1]); | 662 | context_destroy(&c->context[1]); |
660 | if (i == OCON_ISID || i == OCON_FS || | 663 | if (i == OCON_ISID || i == OCON_FS || |
@@ -1773,6 +1776,131 @@ out: | |||
1773 | return rc; | 1776 | return rc; |
1774 | } | 1777 | } |
1775 | 1778 | ||
1779 | static int genfs_read(struct policydb *p, void *fp) | ||
1780 | { | ||
1781 | int i, j, rc; | ||
1782 | u32 nel, nel2, len, len2; | ||
1783 | __le32 buf[1]; | ||
1784 | struct ocontext *l, *c; | ||
1785 | struct ocontext *newc = NULL; | ||
1786 | struct genfs *genfs_p, *genfs; | ||
1787 | struct genfs *newgenfs = NULL; | ||
1788 | |||
1789 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1790 | if (rc) | ||
1791 | goto out; | ||
1792 | nel = le32_to_cpu(buf[0]); | ||
1793 | |||
1794 | for (i = 0; i < nel; i++) { | ||
1795 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1796 | if (rc) | ||
1797 | goto out; | ||
1798 | len = le32_to_cpu(buf[0]); | ||
1799 | |||
1800 | rc = -ENOMEM; | ||
1801 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
1802 | if (!newgenfs) | ||
1803 | goto out; | ||
1804 | |||
1805 | rc = -ENOMEM; | ||
1806 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | ||
1807 | if (!newgenfs->fstype) | ||
1808 | goto out; | ||
1809 | |||
1810 | rc = next_entry(newgenfs->fstype, fp, len); | ||
1811 | if (rc) | ||
1812 | goto out; | ||
1813 | |||
1814 | newgenfs->fstype[len] = 0; | ||
1815 | |||
1816 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
1817 | genfs_p = genfs, genfs = genfs->next) { | ||
1818 | rc = -EINVAL; | ||
1819 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
1820 | printk(KERN_ERR "SELinux: dup genfs fstype %s\n", | ||
1821 | newgenfs->fstype); | ||
1822 | goto out; | ||
1823 | } | ||
1824 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
1825 | break; | ||
1826 | } | ||
1827 | newgenfs->next = genfs; | ||
1828 | if (genfs_p) | ||
1829 | genfs_p->next = newgenfs; | ||
1830 | else | ||
1831 | p->genfs = newgenfs; | ||
1832 | genfs = newgenfs; | ||
1833 | newgenfs = NULL; | ||
1834 | |||
1835 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1836 | if (rc) | ||
1837 | goto out; | ||
1838 | |||
1839 | nel2 = le32_to_cpu(buf[0]); | ||
1840 | for (j = 0; j < nel2; j++) { | ||
1841 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1842 | if (rc) | ||
1843 | goto out; | ||
1844 | len = le32_to_cpu(buf[0]); | ||
1845 | |||
1846 | rc = -ENOMEM; | ||
1847 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
1848 | if (!newc) | ||
1849 | goto out; | ||
1850 | |||
1851 | rc = -ENOMEM; | ||
1852 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
1853 | if (!newc->u.name) | ||
1854 | goto out; | ||
1855 | |||
1856 | rc = next_entry(newc->u.name, fp, len); | ||
1857 | if (rc) | ||
1858 | goto out; | ||
1859 | newc->u.name[len] = 0; | ||
1860 | |||
1861 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1862 | if (rc) | ||
1863 | goto out; | ||
1864 | |||
1865 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
1866 | rc = context_read_and_validate(&newc->context[0], p, fp); | ||
1867 | if (rc) | ||
1868 | goto out; | ||
1869 | |||
1870 | for (l = NULL, c = genfs->head; c; | ||
1871 | l = c, c = c->next) { | ||
1872 | rc = -EINVAL; | ||
1873 | if (!strcmp(newc->u.name, c->u.name) && | ||
1874 | (!c->v.sclass || !newc->v.sclass || | ||
1875 | newc->v.sclass == c->v.sclass)) { | ||
1876 | printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n", | ||
1877 | genfs->fstype, c->u.name); | ||
1878 | goto out; | ||
1879 | } | ||
1880 | len = strlen(newc->u.name); | ||
1881 | len2 = strlen(c->u.name); | ||
1882 | if (len > len2) | ||
1883 | break; | ||
1884 | } | ||
1885 | |||
1886 | newc->next = c; | ||
1887 | if (l) | ||
1888 | l->next = newc; | ||
1889 | else | ||
1890 | genfs->head = newc; | ||
1891 | newc = NULL; | ||
1892 | } | ||
1893 | } | ||
1894 | rc = 0; | ||
1895 | out: | ||
1896 | if (newgenfs) | ||
1897 | kfree(newgenfs->fstype); | ||
1898 | kfree(newgenfs); | ||
1899 | ocontext_destroy(newc, OCON_FSUSE); | ||
1900 | |||
1901 | return rc; | ||
1902 | } | ||
1903 | |||
1776 | /* | 1904 | /* |
1777 | * Read the configuration data from a policy database binary | 1905 | * Read the configuration data from a policy database binary |
1778 | * representation file into a policy database structure. | 1906 | * representation file into a policy database structure. |
@@ -1781,12 +1909,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
1781 | { | 1909 | { |
1782 | struct role_allow *ra, *lra; | 1910 | struct role_allow *ra, *lra; |
1783 | struct role_trans *tr, *ltr; | 1911 | struct role_trans *tr, *ltr; |
1784 | struct ocontext *l, *c, *newc; | 1912 | struct ocontext *l, *c; |
1785 | struct genfs *genfs_p, *genfs, *newgenfs; | ||
1786 | int i, j, rc; | 1913 | int i, j, rc; |
1787 | __le32 buf[4]; | 1914 | __le32 buf[4]; |
1788 | u32 nodebuf[8]; | 1915 | u32 nodebuf[8]; |
1789 | u32 len, len2, nprim, nel, nel2; | 1916 | u32 len, nprim, nel; |
1917 | |||
1790 | char *policydb_str; | 1918 | char *policydb_str; |
1791 | struct policydb_compat_info *info; | 1919 | struct policydb_compat_info *info; |
1792 | 1920 | ||
@@ -2099,107 +2227,9 @@ int policydb_read(struct policydb *p, void *fp) | |||
2099 | } | 2227 | } |
2100 | } | 2228 | } |
2101 | 2229 | ||
2102 | rc = next_entry(buf, fp, sizeof(u32)); | 2230 | rc = genfs_read(p, fp); |
2103 | if (rc < 0) | 2231 | if (rc) |
2104 | goto bad; | 2232 | goto bad; |
2105 | nel = le32_to_cpu(buf[0]); | ||
2106 | genfs_p = NULL; | ||
2107 | rc = -EINVAL; | ||
2108 | for (i = 0; i < nel; i++) { | ||
2109 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2110 | if (rc < 0) | ||
2111 | goto bad; | ||
2112 | len = le32_to_cpu(buf[0]); | ||
2113 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
2114 | if (!newgenfs) { | ||
2115 | rc = -ENOMEM; | ||
2116 | goto bad; | ||
2117 | } | ||
2118 | |||
2119 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | ||
2120 | if (!newgenfs->fstype) { | ||
2121 | rc = -ENOMEM; | ||
2122 | kfree(newgenfs); | ||
2123 | goto bad; | ||
2124 | } | ||
2125 | rc = next_entry(newgenfs->fstype, fp, len); | ||
2126 | if (rc < 0) { | ||
2127 | kfree(newgenfs->fstype); | ||
2128 | kfree(newgenfs); | ||
2129 | goto bad; | ||
2130 | } | ||
2131 | newgenfs->fstype[len] = 0; | ||
2132 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
2133 | genfs_p = genfs, genfs = genfs->next) { | ||
2134 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
2135 | printk(KERN_ERR "SELinux: dup genfs " | ||
2136 | "fstype %s\n", newgenfs->fstype); | ||
2137 | kfree(newgenfs->fstype); | ||
2138 | kfree(newgenfs); | ||
2139 | goto bad; | ||
2140 | } | ||
2141 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
2142 | break; | ||
2143 | } | ||
2144 | newgenfs->next = genfs; | ||
2145 | if (genfs_p) | ||
2146 | genfs_p->next = newgenfs; | ||
2147 | else | ||
2148 | p->genfs = newgenfs; | ||
2149 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2150 | if (rc < 0) | ||
2151 | goto bad; | ||
2152 | nel2 = le32_to_cpu(buf[0]); | ||
2153 | for (j = 0; j < nel2; j++) { | ||
2154 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2155 | if (rc < 0) | ||
2156 | goto bad; | ||
2157 | len = le32_to_cpu(buf[0]); | ||
2158 | |||
2159 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
2160 | if (!newc) { | ||
2161 | rc = -ENOMEM; | ||
2162 | goto bad; | ||
2163 | } | ||
2164 | |||
2165 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
2166 | if (!newc->u.name) { | ||
2167 | rc = -ENOMEM; | ||
2168 | goto bad_newc; | ||
2169 | } | ||
2170 | rc = next_entry(newc->u.name, fp, len); | ||
2171 | if (rc < 0) | ||
2172 | goto bad_newc; | ||
2173 | newc->u.name[len] = 0; | ||
2174 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2175 | if (rc < 0) | ||
2176 | goto bad_newc; | ||
2177 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
2178 | if (context_read_and_validate(&newc->context[0], p, fp)) | ||
2179 | goto bad_newc; | ||
2180 | for (l = NULL, c = newgenfs->head; c; | ||
2181 | l = c, c = c->next) { | ||
2182 | if (!strcmp(newc->u.name, c->u.name) && | ||
2183 | (!c->v.sclass || !newc->v.sclass || | ||
2184 | newc->v.sclass == c->v.sclass)) { | ||
2185 | printk(KERN_ERR "SELinux: dup genfs " | ||
2186 | "entry (%s,%s)\n", | ||
2187 | newgenfs->fstype, c->u.name); | ||
2188 | goto bad_newc; | ||
2189 | } | ||
2190 | len = strlen(newc->u.name); | ||
2191 | len2 = strlen(c->u.name); | ||
2192 | if (len > len2) | ||
2193 | break; | ||
2194 | } | ||
2195 | |||
2196 | newc->next = c; | ||
2197 | if (l) | ||
2198 | l->next = newc; | ||
2199 | else | ||
2200 | newgenfs->head = newc; | ||
2201 | } | ||
2202 | } | ||
2203 | 2233 | ||
2204 | rc = range_read(p, fp); | 2234 | rc = range_read(p, fp); |
2205 | if (rc) | 2235 | if (rc) |
@@ -2227,8 +2257,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
2227 | rc = 0; | 2257 | rc = 0; |
2228 | out: | 2258 | out: |
2229 | return rc; | 2259 | return rc; |
2230 | bad_newc: | ||
2231 | ocontext_destroy(newc, OCON_FSUSE); | ||
2232 | bad: | 2260 | bad: |
2233 | if (!rc) | 2261 | if (!rc) |
2234 | rc = -EINVAL; | 2262 | rc = -EINVAL; |