LCOV - code coverage report
Current view: top level - source3/torture - test_cleanup.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 56 94 59.6 %
Date: 2024-06-13 04:01:37 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Test cleanup behaviour
       4             :    Copyright (C) Volker Lendecke 2011
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "locking/proto.h"
      22             : #include "torture/proto.h"
      23             : #include "system/filesys.h"
      24             : #include "system/select.h"
      25             : #include "libsmb/libsmb.h"
      26             : #include "libcli/smb/smbXcli_base.h"
      27             : #include "libcli/security/security.h"
      28             : #include "librpc/gen_ndr/open_files.h"
      29             : 
      30           3 : bool run_cleanup1(int dummy)
      31             : {
      32             :         struct cli_state *cli;
      33           3 :         const char *fname = "\\cleanup1";
      34             :         uint16_t fnum;
      35             :         NTSTATUS status;
      36             : 
      37           3 :         printf("CLEANUP1: Checking that a conflicting share mode is cleaned "
      38             :                "up\n");
      39             : 
      40           3 :         if (!torture_open_connection(&cli, 0)) {
      41           2 :                 return false;
      42             :         }
      43           1 :         status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum);
      44           1 :         if (!NT_STATUS_IS_OK(status)) {
      45           0 :                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
      46           0 :                 return false;
      47             :         }
      48           1 :         status = smbXcli_conn_samba_suicide(cli->conn, 1);
      49           1 :         if (!NT_STATUS_IS_OK(status)) {
      50           0 :                 printf("smbXcli_conn_samba_suicide failed: %s\n",
      51             :                        nt_errstr(status));
      52           0 :                 return false;
      53             :         }
      54             : 
      55           1 :         if (!torture_open_connection(&cli, 1)) {
      56           0 :                 return false;
      57             :         }
      58           1 :         status = cli_ntcreate(
      59             :                 cli, fname, 0,
      60             :                 FILE_GENERIC_READ|FILE_GENERIC_WRITE|DELETE_ACCESS,
      61             :                 FILE_ATTRIBUTE_NORMAL,
      62             :                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
      63             :                 FILE_OPEN, FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
      64           1 :         if (!NT_STATUS_IS_OK(status)) {
      65           0 :                 printf("2nd open of %s failed (%s)\n", fname,
      66             :                        nt_errstr(status));
      67           0 :                 return false;
      68             :         }
      69           1 :         cli_close(cli, fnum);
      70             : 
      71           1 :         torture_close_connection(cli);
      72           1 :         return NT_STATUS_IS_OK(status);
      73             : }
      74             : 
      75           1 : bool run_cleanup2(int dummy)
      76             : {
      77             :         struct cli_state *cli1, *cli2, *cli3;
      78           1 :         const char *fname = "\\cleanup2";
      79             :         uint16_t fnum1, fnum2, fnum3;
      80             :         NTSTATUS status;
      81             :         char buf;
      82             : 
      83           1 :         printf("CLEANUP2: Checking that a conflicting brlock is cleaned up\n");
      84             : 
      85           1 :         if (!torture_open_connection(&cli1, 0)) {
      86           0 :                 return false;
      87             :         }
      88           1 :         status = cli_ntcreate(
      89             :                 cli1, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
      90             :                 FILE_ATTRIBUTE_NORMAL,
      91             :                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
      92             :                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
      93           1 :         if (!NT_STATUS_IS_OK(status)) {
      94           0 :                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
      95           0 :                 return false;
      96             :         }
      97           1 :         status = cli_lock32(cli1, fnum1, 0, 1, 0, WRITE_LOCK);
      98           1 :         if (!NT_STATUS_IS_OK(status)) {
      99           0 :                 printf("lock failed (%s)\n", nt_errstr(status));
     100           0 :                 return false;
     101             :         }
     102             : 
     103           1 :         if (!torture_open_connection(&cli3, 1)) {
     104           0 :                 return false;
     105             :         }
     106           1 :         status = cli_ntcreate(
     107             :                 cli3, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
     108             :                 FILE_ATTRIBUTE_NORMAL,
     109             :                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
     110             :                 FILE_OVERWRITE_IF, 0, 0, &fnum3, NULL);
     111           1 :         if (!NT_STATUS_IS_OK(status)) {
     112           0 :                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
     113           0 :                 return false;
     114             :         }
     115           1 :         status = cli_lock32(cli3, fnum3, 1, 1, 0, WRITE_LOCK);
     116           1 :         if (!NT_STATUS_IS_OK(status)) {
     117           0 :                 printf("lock failed (%s)\n", nt_errstr(status));
     118           0 :                 return false;
     119             :         }
     120             : 
     121           1 :         status = cli_lock32(cli1, fnum1, 2, 1, 0, WRITE_LOCK);
     122           1 :         if (!NT_STATUS_IS_OK(status)) {
     123           0 :                 printf("lock failed (%s)\n", nt_errstr(status));
     124           0 :                 return false;
     125             :         }
     126             : 
     127             :         /*
     128             :          * Check the file is indeed locked
     129             :          */
     130           1 :         if (!torture_open_connection(&cli2, 1)) {
     131           0 :                 return false;
     132             :         }
     133           1 :         status = cli_ntcreate(
     134             :                 cli2, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
     135             :                 FILE_ATTRIBUTE_NORMAL,
     136             :                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
     137             :                 FILE_OPEN, 0, 0, &fnum2, NULL);
     138           1 :         if (!NT_STATUS_IS_OK(status)) {
     139           0 :                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
     140           0 :                 return false;
     141             :         }
     142           1 :         buf = 'x';
     143           1 :         status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL);
     144           1 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
     145           0 :                 printf("write succeeded\n");
     146           0 :                 return false;
     147             :         }
     148             : 
     149             :         /*
     150             :          * Kill the lock holder
     151             :          */
     152           1 :         status = smbXcli_conn_samba_suicide(cli1->conn, 1);
     153           1 :         if (!NT_STATUS_IS_OK(status)) {
     154           0 :                 printf("smbXcli_conn_samba_suicide failed: %s\n",
     155             :                        nt_errstr(status));
     156           0 :                 return false;
     157             :         }
     158             : 
     159             :         /*
     160             :          * Give the suicidal smbd a bit of time to really pass away
     161             :          */
     162           1 :         smb_msleep(1000);
     163             : 
     164           1 :         status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL);
     165           1 :         if (!NT_STATUS_IS_OK(status)) {
     166           0 :                 printf("write failed: %s\n", nt_errstr(status));
     167           0 :                 return false;
     168             :         }
     169           1 :         return true;
     170             : }
     171             : 
     172           1 : bool run_cleanup4(int dummy)
     173             : {
     174             :         struct cli_state *cli1, *cli2;
     175           1 :         const char *fname = "\\cleanup4";
     176             :         uint16_t fnum1, fnum2;
     177             :         NTSTATUS status;
     178             : 
     179           1 :         printf("CLEANUP4: Checking that a conflicting share mode is cleaned "
     180             :                "up\n");
     181             : 
     182           1 :         if (!torture_open_connection(&cli1, 0)) {
     183           0 :                 return false;
     184             :         }
     185           1 :         if (!torture_open_connection(&cli2, 0)) {
     186           0 :                 return false;
     187             :         }
     188             : 
     189           1 :         status = cli_ntcreate(
     190             :                 cli1, fname, 0,
     191             :                 FILE_GENERIC_READ|DELETE_ACCESS,
     192             :                 FILE_ATTRIBUTE_NORMAL,
     193             :                 FILE_SHARE_READ|FILE_SHARE_DELETE,
     194             :                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
     195           1 :         if (!NT_STATUS_IS_OK(status)) {
     196           0 :                 printf("creating file failed: %s\n",
     197             :                        nt_errstr(status));
     198           0 :                 return false;
     199             :         }
     200             : 
     201           1 :         status = cli_ntcreate(
     202             :                 cli2, fname, 0,
     203             :                 FILE_GENERIC_READ|DELETE_ACCESS,
     204             :                 FILE_ATTRIBUTE_NORMAL,
     205             :                 FILE_SHARE_READ|FILE_SHARE_DELETE,
     206             :                 FILE_OPEN, 0, 0, &fnum2, NULL);
     207           1 :         if (!NT_STATUS_IS_OK(status)) {
     208           0 :                 printf("opening file 1st time failed: %s\n",
     209             :                        nt_errstr(status));
     210           0 :                 return false;
     211             :         }
     212             : 
     213           1 :         status = smbXcli_conn_samba_suicide(cli1->conn, 1);
     214           1 :         if (!NT_STATUS_IS_OK(status)) {
     215           0 :                 printf("smbXcli_conn_samba_suicide failed: %s\n",
     216             :                        nt_errstr(status));
     217           0 :                 return false;
     218             :         }
     219             : 
     220             :         /*
     221             :          * The next open will conflict with both opens above. The first open
     222             :          * above will be correctly cleaned up. A bug in smbd iterating over
     223             :          * the share mode array made it skip the share conflict check for the
     224             :          * second open. Trigger this bug.
     225             :          */
     226             : 
     227           1 :         status = cli_ntcreate(
     228             :                 cli2, fname, 0,
     229             :                 FILE_GENERIC_WRITE|DELETE_ACCESS,
     230             :                 FILE_ATTRIBUTE_NORMAL,
     231             :                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
     232             :                 FILE_OPEN, 0, 0, &fnum2, NULL);
     233           1 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
     234           0 :                 printf("opening file 2nd time returned: %s\n",
     235             :                        nt_errstr(status));
     236           0 :                 return false;
     237             :         }
     238             : 
     239           1 :         return true;
     240             : }

Generated by: LCOV version 1.13