Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: provide a bounded version of label_parse

some label/context sources might not be guaranteed to be null terminiated
provide a size bounded version of label parse to deal with these.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

+27 -11
+3
security/apparmor/include/label.h
··· 327 327 void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp); 328 328 void aa_label_printk(struct aa_label *label, gfp_t gfp); 329 329 330 + struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str, 331 + size_t n, gfp_t gfp, bool create, 332 + bool force_stack); 330 333 struct aa_label *aa_label_parse(struct aa_label *base, const char *str, 331 334 gfp_t gfp, bool create, bool force_stack); 332 335
+24 -11
security/apparmor/label.c
··· 1808 1808 aa_put_ns(ns); 1809 1809 } 1810 1810 1811 - static int label_count_str_entries(const char *str) 1811 + static int label_count_strn_entries(const char *str, size_t n) 1812 1812 { 1813 + const char *end = str + n; 1813 1814 const char *split; 1814 1815 int count = 1; 1815 1816 1816 1817 AA_BUG(!str); 1817 1818 1818 - for (split = aa_label_str_split(str); 1819 + for (split = aa_label_strn_split(str, end - str); 1819 1820 split; 1820 - split = aa_label_str_split(str)) { 1821 + split = aa_label_strn_split(str, end - str)) { 1821 1822 count++; 1822 1823 str = split + 3; 1823 1824 } ··· 1846 1845 } 1847 1846 1848 1847 /** 1849 - * aa_label_parse - parse, validate and convert a text string to a label 1848 + * aa_label_strn_parse - parse, validate and convert a text string to a label 1850 1849 * @base: base label to use for lookups (NOT NULL) 1851 1850 * @str: null terminated text string (NOT NULL) 1851 + * @n: length of str to parse, will stop at \0 if encountered before n 1852 1852 * @gfp: allocation type 1853 1853 * @create: true if should create compound labels if they don't exist 1854 1854 * @force_stack: true if should stack even if no leading & ··· 1857 1855 * Returns: the matching refcounted label if present 1858 1856 * else ERRPTR 1859 1857 */ 1860 - struct aa_label *aa_label_parse(struct aa_label *base, const char *str, 1861 - gfp_t gfp, bool create, bool force_stack) 1858 + struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str, 1859 + size_t n, gfp_t gfp, bool create, 1860 + bool force_stack) 1862 1861 { 1863 1862 DEFINE_VEC(profile, vec); 1864 1863 struct aa_label *label, *currbase = base; 1865 1864 int i, len, stack = 0, error; 1865 + const char *end = str + n; 1866 1866 const char *split; 1867 1867 1868 1868 AA_BUG(!base); 1869 1869 AA_BUG(!str); 1870 1870 1871 - str = skip_spaces(str); 1872 - len = label_count_str_entries(str); 1871 + str = skipn_spaces(str, n); 1872 + if (str == NULL) 1873 + return ERR_PTR(-EINVAL); 1874 + len = label_count_strn_entries(str, end - str); 1873 1875 if (*str == '&' || force_stack) { 1874 1876 /* stack on top of base */ 1875 1877 stack = base->size; ··· 1891 1885 for (i = 0; i < stack; i++) 1892 1886 vec[i] = aa_get_profile(base->vec[i]); 1893 1887 1894 - for (split = aa_label_str_split(str), i = stack; 1888 + for (split = aa_label_strn_split(str, end - str), i = stack; 1895 1889 split && i < len; i++) { 1896 1890 vec[i] = fqlookupn_profile(base, currbase, str, split - str); 1897 1891 if (!vec[i]) ··· 1903 1897 if (vec[i]->ns != labels_ns(currbase)) 1904 1898 currbase = &vec[i]->label; 1905 1899 str = split + 3; 1906 - split = aa_label_str_split(str); 1900 + split = aa_label_strn_split(str, end - str); 1907 1901 } 1908 1902 /* last element doesn't have a split */ 1909 1903 if (i < len) { 1910 - vec[i] = fqlookupn_profile(base, currbase, str, strlen(str)); 1904 + vec[i] = fqlookupn_profile(base, currbase, str, end - str); 1911 1905 if (!vec[i]) 1912 1906 goto fail; 1913 1907 } ··· 1937 1931 fail: 1938 1932 label = ERR_PTR(-ENOENT); 1939 1933 goto out; 1934 + } 1935 + 1936 + struct aa_label *aa_label_parse(struct aa_label *base, const char *str, 1937 + gfp_t gfp, bool create, bool force_stack) 1938 + { 1939 + return aa_label_strn_parse(base, str, strlen(str), gfp, create, 1940 + force_stack); 1940 1941 } 1941 1942 1942 1943 /**