dbwrap: Add overflow protection to dbwrap_record_watchers_key()
authorVolker Lendecke <vl@samba.org>
Tue, 12 Jul 2016 13:57:29 +0000 (15:57 +0200)
committerVolker Lendecke <vl@samba.org>
Fri, 15 Jul 2016 14:56:13 +0000 (16:56 +0200)
It's highly unlinkely that this will ever kick in, because our current tdb keys
are rather small, but offset calculations without overflow checks are bad.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/lib/dbwrap/dbwrap_watch.c

index 714c54d596f3f070027085d76740a9dd06c71216..a6e032a722a2fd3a769005db48273ada3b3eb8cd 100644 (file)
@@ -46,9 +46,9 @@ static struct db_context *dbwrap_record_watchers_db(void)
        return watchers_db;
 }
 
-static size_t dbwrap_record_watchers_key(struct db_context *db,
-                                        struct db_record *rec,
-                                        uint8_t *wkey, size_t wkey_len)
+static ssize_t dbwrap_record_watchers_key(struct db_context *db,
+                                         struct db_record *rec,
+                                         uint8_t *wkey, size_t wkey_len)
 {
        size_t db_id_len = dbwrap_db_id(db, NULL, 0);
        uint8_t db_id[db_id_len];
@@ -59,7 +59,15 @@ static size_t dbwrap_record_watchers_key(struct db_context *db,
 
        key = dbwrap_record_get_key(rec);
 
-       needed = sizeof(uint32_t) + db_id_len + key.dsize;
+       needed = sizeof(uint32_t) + db_id_len;
+       if (needed < sizeof(uint32_t)) {
+               return -1;
+       }
+
+       needed += key.dsize;
+       if (needed < key.dsize) {
+               return -1;
+       }
 
        if (wkey_len >= needed) {
                SIVAL(wkey, 0, db_id_len);
@@ -221,6 +229,7 @@ struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
        struct dbwrap_record_watch_state *state;
        struct db_context *watchers_db;
        NTSTATUS status;
+       ssize_t needed;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct dbwrap_record_watch_state);
@@ -239,8 +248,12 @@ struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       state->w_key.dsize = dbwrap_record_watchers_key(
-               state->db, rec, NULL, 0);
+       needed = dbwrap_record_watchers_key(state->db, rec, NULL, 0);
+       if (needed == -1) {
+               tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
+               return tevent_req_post(req, ev);
+       }
+       state->w_key.dsize = needed;
 
        state->w_key.dptr = talloc_array(state, uint8_t, state->w_key.dsize);
        if (tevent_req_nomem(state->w_key.dptr, req)) {