Coverage Report

Created: 2026-07-16 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pam_ipmi_fuzzer.c
Line
Count
Source
1
/*
2
 * Copyright 2026 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <stdint.h>
18
#include <stddef.h>
19
#include <stdlib.h>
20
#include <string.h>
21
#include <unistd.h>
22
#include <stdio.h>
23
24
#include <security/pam_modules.h>
25
#include <security/pam_ext.h>
26
27
// Mocking some functions that might be problematic
28
0
int lckpwdf(void) { return 0; }
29
0
int ulckpwdf(void) { return 0; }
30
31
// The function we want to fuzz
32
int update_pass_special_file(const pam_handle_t *pamh, const char *keyfilename,
33
           const char *filename, const char *forwho,
34
           const char *towhat);
35
36
1
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
37
1
    if (size < 10) return 0;
38
39
1
    char key_file[] = "/tmp/fuzz_key_XXXXXX";
40
1
    int key_fd = mkstemp(key_file);
41
1
    if (key_fd == -1) return 0;
42
    // key file must be 8 bytes as per pam_ipmisave.c: MAX_KEY_SIZE
43
1
    uint8_t key_data[8] = {0};
44
1
    if (size >= 8) {
45
1
        memcpy(key_data, data, 8);
46
1
        data += 8;
47
1
        size -= 8;
48
1
    }
49
1
    write(key_fd, key_data, 8);
50
1
    close(key_fd);
51
52
1
    char pass_file[] = "/tmp/fuzz_pass_XXXXXX";
53
1
    int pass_fd = mkstemp(pass_file);
54
1
    if (pass_fd == -1) {
55
0
        unlink(key_file);
56
0
        return 0;
57
0
    }
58
1
    if (size > 0) {
59
        // Use half of remaining data for the initial pass file content
60
1
        size_t initial_file_size = size / 2;
61
1
        write(pass_fd, data, initial_file_size);
62
1
        data += initial_file_size;
63
1
        size -= initial_file_size;
64
1
    }
65
1
    close(pass_fd);
66
67
1
    if (size < 2) {
68
0
        unlink(key_file);
69
0
        unlink(pass_file);
70
0
        return 0;
71
0
    }
72
73
    // Use the rest for username and password
74
1
    size_t user_len = size / 2;
75
1
    char *user = malloc(user_len + 1);
76
1
    memcpy(user, data, user_len);
77
1
    user[user_len] = '\0';
78
1
    data += user_len;
79
1
    size -= user_len;
80
81
1
    char *pass = malloc(size + 1);
82
1
    memcpy(pass, data, size);
83
1
    pass[size] = '\0';
84
85
    // Call the function
86
1
    update_pass_special_file(NULL, key_file, pass_file, user, pass);
87
88
1
    free(user);
89
1
    free(pass);
90
1
    unlink(key_file);
91
1
    unlink(pass_file);
92
93
1
    return 0;
94
1
}