X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/a991bd8d3e7fe02dbca0644054bab73c5b75324a..HEAD:/bsd/kern/subr_sbuf.c diff --git a/bsd/kern/subr_sbuf.c b/bsd/kern/subr_sbuf.c index 190485145..8196722e9 100644 --- a/bsd/kern/subr_sbuf.c +++ b/bsd/kern/subr_sbuf.c @@ -705,147 +705,6 @@ sbuf_done(struct sbuf *s) return !!SBUF_ISFINISHED(s); } -/*! - * @function sbuf_uionew - * - * @brief - * Create a new sbuf and initialize its buffer with data from the given uio. - * - * @param s - * An optional existing sbuf to initialize, or NULL to allocate a new one. - * - * @param uio - * The uio describing the data to populate the sbuf with. - * - * @param error - * An output parameter to report any error to. - * - * @returns - * The new and/or initialized sbuf, or NULL on error. The error code is - * reported back via @a error. - */ -struct sbuf * -sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) -{ - int size; - - if ((user_size_t)uio_resid(uio) > INT_MAX - 1) { - *error = EINVAL; - return NULL; - } - - size = (int)uio_resid(uio); - s = sbuf_new(s, NULL, size + 1, 0); - if (s == NULL) { - *error = ENOMEM; - return NULL; - } - - *error = uiomove(s->s_buf, size, uio); - if (*error != 0) { - sbuf_delete(s); - return NULL; - } - - s->s_len = size; - *error = 0; - - return s; -} - -/*! - * @function sbuf_bcopyin - * - * @brief - * Append userland data to an sbuf. - * - * @param s - * The sbuf. - * - * @param uaddr - * The userland address of data to append to the sbuf. - * - * @param len - * The length of the data to copy from userland. - * - * @returns - * 0 on success or -1 on error. Always returns -1 if the sbuf is marked as - * overflowed. - */ -int -sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) -{ - if (SBUF_HASOVERFLOWED(s)) { - return -1; - } - - if (len == 0) { - return 0; - } - - if (-1 == sbuf_ensure_capacity(s, len)) { - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - return -1; - } - - if (copyin(CAST_USER_ADDR_T(uaddr), &s->s_buf[s->s_len], len) != 0) { - return -1; - } - - s->s_len += (int)len; - return 0; -} - -/*! - * @function sbuf_copyin - * - * @brief - * Append a userland string to an sbuf. - * - * @param s - * The sbuf. - * - * @param uaddr - * The userland address of the string to append to the sbuf. - * - * @param len - * The maximum length of the string to copy. If zero, the current capacity of - * the sbuf is used. - * - * @returns - * The number of bytes copied or -1 if an error occurred. Always returns -1 if - * the sbuf is marked as overflowed. - */ -int -sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) -{ - size_t done; - - if (SBUF_HASOVERFLOWED(s)) { - return -1; - } - - if (len == 0) { - len = sbuf_capacity(s); - } else if (-1 == sbuf_ensure_capacity(s, len)) { - return -1; - } - - switch (copyinstr(CAST_USER_ADDR_T(uaddr), &s->s_buf[s->s_len], len + 1, &done)) { - case ENAMETOOLONG: - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - s->s_len += done; - return -1; - case 0: - s->s_len += done - 1; - break; - default: - return -1; - } - - return (int)done; -} - #if DEBUG || DEVELOPMENT /* @@ -1932,258 +1791,6 @@ sysctl_sbuf_tests SYSCTL_HANDLER_ARGS } } - SBUF_TESTING("sbuf_uionew") - { - SBUF_SHOULD("reject residuals that are too large") - { - struct sbuf *s = NULL; - uio_t auio = NULL; - char buf[4]; - int error = 0; - - buf[0] = 'A'; - buf[1] = 'B'; - buf[2] = 'C'; - buf[3] = 'D'; - - auio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); - uio_addiov(auio, (user_addr_t)buf, INT_MAX); - - s = sbuf_uionew(NULL, auio, &error); - SBUF_ASSERT_EQ(NULL, s); - SBUF_ASSERT_EQ(EINVAL, error); - - uio_free(auio); - } - - SBUF_SHOULD("initialize using data described by the uio") - { - struct sbuf *s = NULL; - uio_t auio = NULL; - char buf[4]; - int error = 0; - - buf[0] = 'A'; - buf[1] = 'B'; - buf[2] = 'C'; - buf[3] = 'D'; - - auio = uio_create(1, 0, UIO_SYSSPACE, UIO_WRITE); - uio_addiov(auio, (user_addr_t)buf, sizeof(buf)); - - s = sbuf_uionew(NULL, auio, &error); - SBUF_ASSERT_NE(NULL, s); - SBUF_ASSERT_EQ(0, error); - SBUF_ASSERT_EQ(4, s->s_len); - SBUF_ASSERT_EQ('A', s->s_buf[0]); - SBUF_ASSERT_EQ('B', s->s_buf[1]); - SBUF_ASSERT_EQ('C', s->s_buf[2]); - SBUF_ASSERT_EQ('D', s->s_buf[3]); - - sbuf_delete(s); - uio_free(auio); - } - - SBUF_SHOULD("fail gracefully for bad addresses") - { - struct sbuf *s = NULL; - uio_t auio = NULL; - int error = 0; - - auio = uio_create(1, 0, UIO_USERSPACE, UIO_WRITE); - uio_addiov(auio, (user_addr_t)0xdeadUL, 123); - - s = sbuf_uionew(NULL, auio, &error); - SBUF_ASSERT_EQ(NULL, s); - SBUF_ASSERT_NE(0, error); - - uio_free(auio); - } - } - - SBUF_TESTING("sbuf_bcopyin") - { - SBUF_SHOULD("succeed when len is zero") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)req->newptr; - - s = sbuf_new(NULL, NULL, 16, 0); - SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, 0)); - SBUF_ASSERT_EQ(0, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("succeed in the simple case") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)req->newptr; - size_t ulen = req->newlen; - - s = sbuf_new(NULL, NULL, 16, 0); - SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, ulen)); - SBUF_ASSERT_EQ(ulen, (size_t)s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail for invalid userland addresses") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)0xdeadUL; - size_t ulen = req->newlen; - - s = sbuf_new(NULL, NULL, 16, 0); - SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen)); - SBUF_ASSERT_EQ(0, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail for kernel addresses") - { - struct sbuf *s = NULL; - const void *uptr = "abcd"; - size_t ulen = 4; - - s = sbuf_new(NULL, NULL, 16, 0); - SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen)); - SBUF_ASSERT_EQ(0, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail if we don't have capacity for a fixed-len sbuf") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)req->newptr; - size_t ulen = req->newlen; - int len_before; - - s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN); - SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde")); - len_before = s->s_len; - SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen)); - SBUF_ASSERT_EQ(len_before, s->s_len); - SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED)); - - sbuf_delete(s); - } - - SBUF_SHOULD("auto-extend if we don't have capacity for an auto-extend sbuf") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)req->newptr; - size_t ulen = req->newlen; - int len_before; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde")); - len_before = s->s_len; - SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, ulen)); - SBUF_ASSERT_EQ(len_before + (int)ulen, s->s_len); - SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED)); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail if overflowed") - { - struct sbuf *s = NULL; - const void *uptr = (const void *)req->newptr; - size_t ulen = req->newlen; - - s = sbuf_new(NULL, NULL, 16, 0); - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen)); - - sbuf_delete(s); - } - } - - SBUF_TESTING("sbuf_copyin") - { - SBUF_SHOULD("succeed in the simple case") - { - struct sbuf *s = NULL; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(req->newlen + 1, sbuf_copyin(s, (const void *)req->newptr, req->newlen)); - SBUF_ASSERT_EQ(req->newlen, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("use the sbuf capacity if len is zero") - { - struct sbuf *s = NULL; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(req->newlen + 1, sbuf_copyin(s, (const void *)req->newptr, 0)); - SBUF_ASSERT_EQ(req->newlen, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail if we can't extend the sbuf to accommodate") - { - struct sbuf *s = NULL; - - s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN); - SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde")); - SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen)); - - sbuf_delete(s); - } - - SBUF_SHOULD("auto-extend the buffer if necessary") - { - struct sbuf *s = NULL; - int len_before; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde")); - len_before = s->s_len; - SBUF_ASSERT_NE(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen)); - SBUF_ASSERT_GT(len_before, s->s_len); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail if the sbuf is overflowed") - { - struct sbuf *s = NULL; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen)); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail gracefully for an invalid address") - { - struct sbuf *s = NULL; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (void *)0xdeadUL, req->newlen)); - - sbuf_delete(s); - } - - SBUF_SHOULD("fail gracefully for a kernel address") - { - struct sbuf *s = NULL; - const char *ptr = "abcd"; - - s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND); - SBUF_ASSERT_EQ(-1, sbuf_copyin(s, ptr, strlen(ptr))); - - sbuf_delete(s); - } - } - SBUF_TEST_END; }